Security

HTTPS enforcement, API authentication, IP allowlists, backup directory protection, maintenance mode security, and best practices.

What PromptWire can access

PromptWire gives an AI agent direct read/write access to your ProcessWire site: pages, fields, templates, files, and schema. Treat it as a development tool with the same access level as a superuser in the admin.

Local mode

When running with PW_PATH only, PromptWire uses the PHP CLI on your machine. There is no network exposure. Commands execute within your local ProcessWire installation using the same permissions as the PHP process.

The MCP server communicates with Cursor over stdio (standard input/output), not over a network socket. No HTTP server is started for local-only operation.

Rename the API endpoint file

The API endpoint ships as promptwire-api.php, but you should rename it to something non-obvious before deploying (e.g. my-pw-bridge.php). This prevents the URL from being guessable by anyone who has read the documentation. The MCP server uses the full PW_REMOTE_URL as-is with no filename assumption, so just update your mcp.json to match.

Remote API authentication

The remote API endpoint authenticates every request using a shared secret sent in the X-PromptWire-Key header. The key is compared with hash_equals() to prevent timing attacks.

The key is defined in site/config-promptwire.php on the server (or via the PROMPTWIRE_API_KEY environment variable for containerised deployments). It must match the PW_REMOTE_KEY value in your local .cursor/mcp.json.

Key requirements

  • Use a strong, random key. Generate one with openssl rand -hex 32.
  • Use a unique key per site. Do not reuse keys across projects.
  • Do not commit keys to version control. Keep config-promptwire.php out of your repo.

IP allowlisting

For an extra layer of protection, restrict the API to specific IP addresses:

define('PROMPTWIRE_ALLOWED_IPS', '1.2.3.4');

Multiple IPs can be comma-separated. The client IP is read from the X-Forwarded-For header (first hop) or REMOTE_ADDR.

If your IP changes frequently (VPN, mobile), you can leave the allowlist disabled. API key authentication is still enforced on every request.

HTTPS enforcement

The API endpoint enforces HTTPS at the server level. Requests over plain HTTP are rejected with a 403 before the API key is even checked. This prevents accidental exposure of the shared secret in an unencrypted request header.

For local development environments that don't have TLS configured, you can bypass enforcement by defining PROMPTWIRE_ALLOW_HTTP in site/config-promptwire.php:

define('PROMPTWIRE_ALLOW_HTTP', true);

Do not set this on a public-facing server.

Error handling

The API suppresses PHP error output to prevent information leakage. Error details are logged server-side but not returned in API responses. The response includes only a generic error message and an HTTP status code (401, 403, 404, or 500).

Response headers

The API sends the following headers on every response:

  • Cache-Control: no-store and Pragma: no-cache to prevent proxy or browser caching.
  • X-Robots-Tag: noindex, nofollow to keep the endpoint out of search engines.

File access

The sync directory (site/assets/pw-mcp/) includes a .htaccess with Deny from all and a stub index.php to block direct web access. YAML files containing your content are only accessible via the filesystem, not via HTTP.

Backup directory protection

When pw_backup or pw_maintenance creates the backup directory (site/assets/backups/promptwire/), it automatically writes a .htaccess file that denies all web access. SQL dumps and file archives are never reachable via HTTP, even if a misconfigured server exposes the site/assets/ tree.

Maintenance mode

Maintenance mode places a flag file at site/assets/cache/maintenance.flag. While the flag exists, all front-end requests receive a styled 503 page with appropriate Retry-After and noindex headers so search engines don't index the downtime page.

Two classes of request bypass the maintenance gate:

  • Superusers: logged-in ProcessWire superusers see the normal site, so you can verify changes during a deployment.
  • API requests: requests to the PromptWire API endpoint are never blocked, so the agent can continue operating (disabling maintenance mode, running health checks, etc.).

Deployment exclusions

Several PromptWire directories and files are for local development only and should not be deployed to a production server. Exclude them from any deployment tool (Duplicator, rsync, CI pipeline, etc.):

  • .pw-sync/ — local schema snapshots and named site configs. The sites/ subdirectory may contain API keys. This directory has no function on a production server.
  • .cursor/ — Cursor IDE configuration. The mcp.json file contains API keys and machine-specific absolute paths.
  • site/assets/pw-mcp/ — local content sync files (YAML). These are working copies for the AI agent and are not used by the live site.

The only PromptWire files that belong on a production server are:

  • site/modules/PromptWire/ — the module itself (required if you want remote access).
  • Your renamed API endpoint file in the site root (shipped as promptwire-api.php; rename it before deploying).
  • site/config-promptwire.php — the API key config (keep this out of version control).

Safety nets

PromptWire can create, edit, and delete pages, fields, templates, and template fieldgroups. From v1.11 onward it can also mutate production schema when an agent explicitly opts in with dryRun: false. To keep that power from becoming a footgun, every write tool is wrapped in overlapping safety layers.

  • Dry-run default. Every write tool defaults to dryRun: true. The caller must pass dryRun: false explicitly to mutate. An agent that forgets just gets a plan back.
  • Three-tier conflict classifier. Every planned change is tagged as safe, warning, or danger. Dangers block the write unless force: true is also passed; warnings are visible but non-blocking.
  • Module-ownership awareness. Writes targeting ProcessWire core system or permanent flags, FormBuilder-owned templates, Repeater pages, PW core templates (admin, user, role, permission), or module-named fields (mediahub_*, seoneo_*, etc.) are flagged as dangers. Prevents silently breaking form submissions, repeater storage, or admin UI.
  • Fieldset pair integrity. Any edit that would leave a FieldsetOpen or FieldsetTabOpen without its matching _END close (or vice versa) is a danger. Stops half-broken admin UI from shipping.
  • Cross-site drift detection. When a write targets both sites, the MCP layer compares the projected state of both sides and refuses to proceed if they would diverge further (for example, a field has different fieldtypes locally vs remote). Prevents drift from being "fixed" by a well-meaning agent.
  • Audit trail. Every write returns an audit object listing what was removed, added, reordered, and how many save() calls fired. Partial writes surface the exact stopping point so recovery is straightforward.
  • Frontend-usage scan. When removing a field, PromptWire scans site/templates/ for hardcoded references to the field name and flags any hits. Catches custom contact forms, search forms, and any place $page->fieldname is written in PHP templates that the module-ownership check cannot see.
  • Backups. pw_backup wraps WireDatabaseBackup and file archives; run it before any risky write. The backup directory is .htaccess-locked so dumps are never web-reachable.
  • Maintenance mode. pw_maintenance puts the site into a styled 503 during risky deploys. API requests bypass the gate so the agent can keep operating.

None of these remove the operator's responsibility to review plans before applying them. They reduce the chance of a single mistake becoming an outage.

Recommendations

  • Do not install PromptWire on client-facing production sites unless you understand and accept the risk.
  • Always have backups in place. PromptWire can create, edit, and delete pages, fields, and templates.
  • Use the hybrid setup (local reads, remote writes) so your production site only receives explicit push operations, never exploratory queries.
  • Review dry-run previews before applying changes to production.

Last updated