Skip to content

Platforms (WordPress, Drupal) without an agent

Not everything an organisation owns runs on a server you can put an agent on: a WordPress shop at a shared host, a Drupal portal at an agency. A platform in monsys is such a site. It reports to the hub itself through Monsys Connect, a plugin that only talks outbound. The hub never connects to the site: except to read the ownership proof.

  • Inventory: core, PHP and database versions, every plugin and theme with version, active state and update availability. They also appear in Inventory → Components (scope platform), so “where does plugin X run” spans servers, containers and external sites.
  • Vulnerabilities: components are matched against NVD (CPE, version- and edition-aware) and, with a Wordfence Intelligence key, against a mirrored Wordfence feed. KEV flags come from CISA.
  • Hygiene checklist: debug mode, XML-RPC, admin file editing, default admin user, HTTPS, cron, auto-updates, number of administrators.
  • Integrity: core files compared with the official wordpress.org checksums (daily). Drift is the classic web-shell signal.
  • Events: aggregated failed logins (per IP and username) and any account promoted to administrator (reported immediately).
  • Silence detection: no report for 1 h → critical alert, as for an agent. It resolves itself when the site comes back.

Alerts always start with [domain], so a push on your phone reads without opening it.

  1. Inventory → Platforms → Add platform. Choose WordPress, enter a name and the domain (hostname only, e.g. shop.example.com).
  2. Copy the API key (msk_…) and the verify token (mvt_…). The key is shown once; it can be rotated later.
  3. Install and activate the Monsys Connect plugin on the site. Paste key and token under Settings → Monsys Connect and save.
  4. Click Verify in monsys. The plugin publishes the token at https://<domain>/.well-known/monsys-verify.txt (fallback /?monsys_verify=1); the hub fetches it with the same SSRF protection as the pentest layer.
  5. On the first report the status turns active.

A site using DISABLE_WP_CRON needs an external cron that runs the WP-Cron events (the recommended production setup). The plugin detects that and then reports cron as “ok”.

  • The API key is write-only: the only thing behind it is the ingest endpoint. A leaked key can at most post data for that one site: never read anything, never touch another site. Rotate it when in doubt (TOTP).
  • Only the hash of the key is stored. The prefix (msk_3f9a…) is what you see in the UI.
  • The plugin never sends content, visitor data, passwords or raw log lines.
  • Actions (below) are only handed to verified platforms.

An editor can, with TOTP, request an action on a component: update a plugin/theme, deactivate or activate a plugin. The request is Ed25519-signed and handed over in the reply to the plugin’s next heartbeat (≤ 5 min). The plugin still listens to nothing.

Every action runs like this:

  1. Pre-checks: free disk space, write access, no maintenance mode, direct filesystem access.
  2. Backup: zip of the component in wp-content/uploads/monsys-backups/ (protected, last ten kept).
  3. Apply through the WordPress upgrader.
  4. Post-checks: front page, admin-ajax and, if WooCommerce is present, the shop must respond without a fatal error.
  5. If any check fails, the plugin restores the backup automatically and reports rolled back. An action that fails pre-checks changes nothing (failed).

Only reversible actions exist. Core upgrades, deletions and actions on the plugin itself are deliberately impossible. The verdict comes back with the full check trail and shows in the actions list; a successful action is a quiet ✅, a rollback or failure a ⚠️.

Wordfence Intelligence is free, including commercial use, but since 2026 requires an account and API key. Set WORDFENCE_API_KEY in the hub environment; the hub mirrors the scanner feed once an hour and every tenant reads the mirror. Each match shows the required attribution (copyright, licence, link to the record, MITRE notice for CVEs).