Skip to content

Allowlist posture

Security boundary summary for the /api/secure proxy allowlist and query policy.

Allowlist posture (internal)

Deny-by-default is the core posture: if an endpoint method/path/query is not explicitly listed here (and in the endpoint registry), the secure proxy blocks it.

This document is an internal security boundary reference for maintainers. It is not public API documentation. The runtime proxy behavior is the source of truth (from src/lib/secure/endpointRegistry.ts -> src/lib/secure/allowlist.ts); this file summarizes the current allowlist posture to prevent drift.

HWP (HeadlessWP Pro)

Explicit method + path allowlist (deny by default):

  • GET /wp-json/headlesswp/v1/nonce — bootstrap CSRF token (nonce header is fixed to X-WP-Nonce).
  • GET /wp-json/headlesswp/v1/health — public health check.
  • GET /wp-json/headlesswp/v1/store/offers — marketing offers for pricing UI.
  • GET /wp-json/headlesswp/v1/capabilities — extension discovery.
  • POST /wp-json/headlesswp/v1/auth/login — session login.
  • POST /wp-json/headlesswp/v1/auth/register — account registration.
  • POST /wp-json/headlesswp/v1/auth/logout — session logout.
  • GET /wp-json/headlesswp/v1/me — account summary (nonce required by proxy).
  • PATCH /wp-json/headlesswp/v1/me/profile — profile update.
  • GET /wp-json/headlesswp/v1/orders — order list.
  • GET /wp-json/headlesswp/v1/subscriptions — subscription list.
  • POST /wp-json/headlesswp/v1/billing/portal-session — billing portal session.
  • POST /wp-json/headlesswp/v1/store/checkout-session — checkout session.
  • GET /wp-json/headlesswp/v1/store/wc/cart — Store API cart preview bridge.
  • POST /wp-json/headlesswp/v1/store/wc/cart/add-item — ensure checkout product exists in cart preview.
  • POST /wp-json/headlesswp/v1/store/wc/cart/apply-coupon — apply coupon for totals preview.
  • POST /wp-json/headlesswp/v1/store/wc/cart/remove-coupon — remove coupon for totals preview.
  • POST /wp-json/headlesswp/v1/affiliate/track — affiliate attribution tracking.
  • GET /wp-json/headlesswp/v1/affiliates/terms — affiliate terms.
  • GET /wp-json/headlesswp/v1/affiliates/me — affiliate profile.
  • GET /wp-json/headlesswp/v1/affiliates/referrals — affiliate referrals.
  • GET /wp-json/headlesswp/v1/affiliates/stats — affiliate stats.
  • POST /wp-json/headlesswp/v1/affiliates/apply — affiliate application.
  • POST /wp-json/headlesswp/v1/affiliates/accept-terms — affiliate terms acceptance.

Allowed query keys (default none):

  • GET /wp-json/headlesswp/v1/nonce: cb (cache-bust for nonce freshness)
  • GET /wp-json/headlesswp/v1/orders: page, perPage
  • POST /wp-json/headlesswp/v1/store/checkout-session: ref, campaign, utm_source, utm_medium, utm_campaign, utm_content
  • GET /wp-json/headlesswp/v1/affiliates/referrals: limit, cursor
  • GET /wp-json/headlesswp/v1/affiliates/stats: range

All other HWP reads proxied through /api/secure/** require X-WP-Nonce per proxy policy.

Store cart bridge POSTs (/store/wc/cart/add-item, /apply-coupon, /remove-coupon) also forward Woo Store API Nonce when available. This header is distinct from X-WP-Nonce and is allowlisted explicitly at the proxy boundary.

PFP (Protected Files Pro)

Explicit allowlist only (no prefix allow):

  • GET /wp-json/protected-files-pro/v1/me/licenses — license list for the account portal.
  • GET /wp-json/protected-files-pro/v1/me/licenses/{licenseId} — license detail for the account portal.
  • POST /wp-json/protected-files-pro/v1/me/reauth — issue short-lived one-time token for license key recovery/rotation.
  • GET /wp-json/protected-files-pro/v1/me/licenses/{licenseId}/key — one-time license key reveal for the account portal (requires X-PFP-Reauth-Token from /me/reauth).
  • GET /wp-json/protected-files-pro/v1/me/licenses/{licenseId}/activations — activation list for a license.
  • POST /wp-json/protected-files-pro/v1/me/licenses/{licenseId}/activations/{activationId}/unlink — unlink a license activation.

Allowed query keys (default none):

  • GET /wp-json/protected-files-pro/v1/me/licenses: page, per_page
  • GET /wp-json/protected-files-pro/v1/me/licenses/{licenseId}/activations: page, per_page

PFP surface area is intentionally minimal; add routes only with fixtures + contract updates.

Default deny posture

  • Any path not in the explicit allowlist is blocked.
  • The proxy hard blocks unrelated namespaces (for example: /wp-json/wp/v2/**, /wp-json/wc/**).
  • Requests with disallowed query keys are blocked (no silent drops).