Witen

Application protection

WordPress plugin guide

Witen Blocker evaluates requests inside WordPress, keeps a local blocklist cache, reports WordPress-specific security evidence after enrollment, and provides security administration and scanning tools. It can connect directly to the hosted collector or cooperate with Warden on the same host.

Requirements and deployment modes

  • WordPress 6.2 or newer and PHP 8.1 or newer.
  • An administrator account that can install and activate plugins.
  • For shared intelligence: a Witen account and an unused protected-asset slot. Local login protection, bot controls, and file-integrity checks work without enrollment.
  • Outbound HTTPS access to the collector for hosted mode, or access to Warden’s ingestion socket for local mode.

Collector mode

Best for shared hosting. WordPress exchanges its enrollment token over HTTPS, synchronizes blocklists and signed catalogs, and sends bounded security-event batches directly.

Warden socket mode

Best when Warden runs on the host. The plugin submits application context over a local Unix socket; Warden correlates it with access-log evidence and remains the firewall authority.

Install the plugin

  1. Download the current witen-blocker ZIP from the authenticated Downloads page.
  2. Compare the file’s SHA-256 checksum with the value shown beside the download.
  3. In WordPress, open Plugins → Add New Plugin → Upload Plugin.
  4. Select the ZIP, install it, and activate Witen Blocker.
  5. Open the new Witen menu and review Settings before enrolling.

Enroll the WordPress installation

  1. In the customer website, open Add Protected Asset and choose WordPress.
  2. Give the installation a stable name and generate a single-use enrollment token.
  3. Either paste the token into Witen → Settings, or define it in wp-config.php before WordPress’s “stop editing” line.
  4. Allow WordPress background maintenance to exchange it for a per-installation credential.
  5. Return to Witen → Settings and confirm the installation reports as enrolled. Remove the consumed token from wp-config.php.
define( 'WITEN_ENROLLMENT_TOKEN', 'wte-one-time-token' );

// Optional only for a managed/self-hosted collector override.
define( 'WITEN_COLLECTOR_URL', 'https://collector.example' );

// Optional local Warden transport.
define( 'WITEN_SOCKET_PATH', '/run/witen/warden-ingest.sock' );
define( 'WITEN_WARDEN_CREDENTIAL_FILE', '/var/lib/witen-wordpress/caller.token' );

// Optional stable override; otherwise Witen derives an installation identity.
define( 'WITEN_SITE_ID', 'shop-production' );
define( 'WITEN_SYNC_INTERVAL', 300 );

Verify protection after enrollment

  • Witen → Settings reports an installation credential and a healthy recent maintenance heartbeat.
  • The Dashboard identifies the expected connection mode: local Warden socket or collector HTTPS.
  • A blocklist synchronization has completed and shows a non-error status.
  • The customer website lists the WordPress asset and a recent report.
  • WordPress cron is functioning; a ten-minute maintenance stall produces an administrator warning.

Use the Witen administration pages

PageUse it forImportant distinction
DashboardConnection health, block statistics, recent events, and recent blocks.A security event is evidence; it is not automatically an applied block.
Blocked IPsReview manual and automatic application-layer blocks; perform bounded bulk actions.Warden firewall state remains authoritative in socket mode.
AllowlistProtect trusted exact addresses from plugin blocking.Review entries periodically; a broad or stale allowlist weakens protection.
Known BotsChoose behavior for recognized crawlers and monitoring services.Identity requires network and User-Agent agreement, not a claimed User-Agent alone.
SettingsEnrollment, transport, sync, local login jail, and configuration-source status.Constants in wp-config.php intentionally override editable settings.
Security ScanIntegrity, malware, suspicious PHP, risky users, and hardening checks.Review evidence before changing or deleting a file.
.htaccessReview and manage supported Apache hardening with backups.Not applicable to nginx, Caddy, or hosts that ignore .htaccess.

Login jail fallback

Without Warden, the plugin maintains a bounded sliding window for WordPress login failures. Configure the window, maximum failures, and ban duration under Settings. With Warden semantic mode, the plugin contributes WordPress facts while Warden evaluates policy and enforcement without double-counting the matching access-log request.

Security scanning and signed catalogs

After enrollment, the plugin downloads the catalog appropriate to the installation’s tier. Catalogs are bounded JSON data, gzip-compressed and Ed25519-signed. The plugin verifies the key identity, signature, payload hash, schema, timestamps, size, rule count, and rollback ordering before caching them. Catalog content is never executed as PHP.

  1. Open Witen → Security Scan and start with the summary.
  2. Review the file path, finding type, evidence, and severity.
  3. Compare unexpected files with a known-good release or backup.
  4. Quarantine or remove only after confirming the file is not legitimate application code.
  5. Re-run the scan and check application behavior after remediation.

Data and privacy boundaries

Sent after enrollment

  • Security-relevant source IP, event category, request method and URI, User-Agent, and bounded contextual fields.
  • Installation identity and runtime inventory needed for compatibility and CVE exposure.
  • Attempted usernames can appear in authentication security events; passwords, cookies, and form bodies are not sent.

Retained locally

  • A bounded delivery queue for undelivered enrolled events.
  • Recent dashboard events and blocks, local block and allow lists, health counters, and the last verified signed catalog.
  • Before enrollment, observations remain local and are not retroactively queued for upload.

WITEN_NO_TELEMETRY disables daily WordPress, PHP, and plugin inventory reporting. Essential connected security-event sharing remains part of the protection model; use offline mode or deactivate the plugin if security events must not leave the site.

WordPress Multisite

Security state, queues, schedules, and node identity are maintained per blog. Unless WITEN_SITE_ID is explicitly defined, the derived identity includes the blog ID, such as example.com#blog-7. An explicit shared site ID is an operator decision and should remain unique for every independently reported installation.

  • Activate and enroll each intended site in the correct network context.
  • Confirm each subsite appears as the expected protected asset.
  • Do not copy one stored installation credential between blogs.
  • Test WordPress cron and blocklist synchronization for the individual site, not only the network main site.

Upgrade, rotate, and recover

Upgrade

  1. Take a normal WordPress database and filesystem backup.
  2. Download and verify the new ZIP.
  3. Replace the plugin through the WordPress updater or your deployment system without deleting Witen options first.
  4. Confirm the displayed version, enrollment state, maintenance heartbeat, blocklist sync, and security scan catalog.

Rotate a credential

Rotate the installation from the customer website. If the credential lives in wp-config.php, update WITEN_SENSOR_CREDENTIAL during the coordinated rotation. A consumed enrollment token cannot be reused.

Uninstall

Uninstall removes plugin options, transients, scheduled actions, and plugin tables from WordPress. It does not itself request deletion of already submitted collector data; use the account/customer deletion process for that separate scope.

Troubleshooting

Enrollment remains pending

  • Confirm the token starts with the expected enrollment prefix and has not already been consumed.
  • Check WordPress cron and the maintenance heartbeat.
  • Verify HTTPS connectivity and system time for TLS and signed-document validation.
  • Remove legacy WITEN_API_KEY; it is intentionally rejected for collector access.

Socket mode is unavailable

  • Confirm Warden is running and the configured path is its ingestion socket, not an arbitrary Docker localhost address.
  • Grant the PHP/web-server process only the filesystem group access needed for ingestion.
  • Check socket ownership and mode after every Warden restart.
  • Remember that the ingestion socket cannot ban, unban, or perform administrative operations.

Blocklists or catalogs are stale

  • Check the last maintenance run and collector reachability.
  • Confirm the installation credential remains valid.
  • The plugin continues using its last verified blocklist/catalog during an outage; signature or rollback failures deliberately reject a replacement.

A legitimate visitor is blocked

  • Review the source address and reason under Blocked IPs.
  • Verify reverse-proxy client IP configuration before allowlisting; otherwise you may allow a proxy rather than the visitor.
  • Add the narrowest exact address to Allowlist, then remove the active plugin block.
  • If Warden enforces the address, investigate and unban it through Warden separately.