Skip to content

Security

Nick Hamze edited this page Sep 1, 2026 · 6 revisions

Security

Fleet uses WordPress Core Application Passwords. It never asks for, receives, or stores a person's normal WordPress sign-in password.

Authority and permissions

An Application Password authenticates as the WordPress user who approved it. It does not bypass WordPress: every Core and plugin REST route still runs its normal permission callback, capability checks, validation, and sanitization.

Fleet is intended for whole-site administration, including installing OpenStation. Connect while signed into an administrator account that has the capabilities required for the work Fleet should perform. Use a less-privileged account only when a deliberately smaller API surface is desired.

Approval protection

  • Fleet discovers the authorization endpoint from the target's WordPress REST index.
  • The endpoint must share the target site's HTTPS origin.
  • A random state UUID and WordPress nonce bind the callback to the initiating hub user and attempt.
  • Pending attempts expire after ten minutes and are consumed once.
  • The callback rejects a different returned site origin, missing username, missing credential, rejection, or failed introspection.
  • Reconnecting an existing site reuses its record instead of creating another Application Password.

Storage on the hub

Connections belong to the current hub user and are stored in user meta. Application Passwords are encrypted with sodium secret-box encryption. Fleet derives the encryption key from the hub's WordPress authentication salt.

Changing that salt makes stored credentials unreadable; reconnect affected sites after a salt rotation. Fleet loads WordPress's bundled sodium compatibility layer when the PHP extension is unavailable and refuses to save a secret if encryption cannot be provided.

Fleet stores the credential's UUID separately so it can revoke that exact Application Password. Activity history never includes credentials. The Explorer retains its latest sanitized result in a short-lived per-user transient, limits its size, and never displays authorization headers.

Request boundary

  • Hub and managed site must use HTTPS.
  • Target URLs cannot contain embedded credentials, query strings, or fragments.
  • Remote calls use WordPress safe HTTP functions and keep unsafe-URL rejection enabled.
  • Fleet does not weaken Core's SSRF protections for private or loopback production targets.
  • Explorer routes are resolved only beneath the discovered REST root; they cannot select another host.
  • Fleet blocks the hub from connecting to itself while allowing path-based multisite siblings.
  • Uploaded media is limited to supported image, audio, video, and PDF MIME types and 10 MB.

Fleet-wide reads

Inbox and Search make authenticated reads against existing WordPress Core routes. Core's batch controller is used when available, but it does not grant extra access: every subrequest still runs the same permission checks as a direct request. Fleet falls back to those direct Core requests when batch support is absent.

Fleet-wide results stay inside the current hub user's session and connections. Client names, tags, notes, favorites, and workspace groupings are hub-owned metadata; they are not written to managed sites. Activity history records the action and outcome without response bodies or credentials.

Hub actions

Only hub users with manage_options can open Fleet or submit management actions. Every form mutation uses a WordPress nonce. The post-approval setup request uses a site-specific AJAX nonce. Notice messages come from fixed codes rather than arbitrary query-string content.

Revocation

Disconnect deletes the exact remote Application Password UUID before Fleet removes its local record. If revocation fails, the site remains in Fleet so the manager can retry.

The approving user or a managed-site administrator can also revoke Fleet for OpenStation on hub-domain under Users → Profile → Application Passwords. Fleet will then receive 401 responses until the site is reconnected.

Uninstall and support reports

Plugin uninstall cannot reliably contact every managed site. Disconnect sites first. If Fleet was removed while a credential remained, revoke it from the managed user's profile.

Never log, paste, or include Application Passwords, authorization headers, callback URLs, WordPress salts, or ordinary login passwords in issue reports.

Clone this wiki locally