Security
Protect server secrets and payment Credentials
The core Payment HTTP Authentication Scheme already requires TLS and treats payment Credentials and Receipts as sensitive data. This page covers the operational practices around MPP_SECRET_KEY and server deployments.
Treat MPP_SECRET_KEY as root-of-trust material
MPP_SECRET_KEY binds HMAC-backed Challenge IDs to your server configuration. If an attacker gets the key, they can mint Challenges that appear server-issued for your realm.
- Keep it on trusted servers only.
- Never ship it to browsers, mobile apps, MCP clients, or frontend bundles.
- Use a different key for each environment.
- Never commit it to git or bake it into container images.
Store it in a secrets manager
Use your platform's secret store as the system of record—AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, HashiCorp Vault, or an equivalent service.
Environment variables are a good delivery mechanism at runtime, but they are not a secrets management strategy by themselves. Inject MPP_SECRET_KEY into your process from a managed secret store instead of treating .env files or deployment manifests as the source of truth.
Never log secrets or payment Credentials
Do not log:
MPP_SECRET_KEYAuthorization: PaymentheadersPayment-Receiptheaders
Keep them out of error messages, debugging output, analytics, traces, and support logs. If you need observability, log stable metadata such as request IDs, Challenge IDs, status codes, or payment method names instead.
Handle proxies and caches safely
Treat reverse proxies, CDNs, API gateways, and observability pipelines as part of your threat surface.
- Send
Cache-Control: no-storewith402responses so intermediaries do not cache Challenges. - Send
Cache-Control: privateon successful responses that includePayment-Receipt. - Redact
Authorization: PaymentandPayment-Receiptheaders in proxy logs, trace exporters, and edge analytics. - Do not rely on intermediary-specific
402handling—verify that your deployment forwardsWWW-Authenticateheaders correctly.
Bind paid requests to the actual request
Use Challenge binding to make sure the paid request matches what your server intended to charge for.
- Include a
digestparameter forPOST,PUT, andPATCHrequests so clients cannot change the request body after receiving a Challenge. - Verify the expected amount, currency, recipient, and route-level business context when checking a Credential.
- Do not use
descriptionas an authorization input. It is display text, not a security control.
Rotate with overlap
When you rotate MPP_SECRET_KEY, use a staged rollout so in-flight Challenges keep working:
- Start issuing new Challenges with the new key.
- Continue verifying the previous key during a short overlap window.
- Remove the old key after outstanding Challenges have expired.
If your deployment does not support current-and-previous-key verification yet, do a coordinated rollout and wait for the old Challenge TTL window to pass before invalidating the previous key.
Respond to exposure immediately
If MPP_SECRET_KEY is exposed:
- Rotate it immediately.
- Remove the old key after your overlap window ends.
- Scrub logs, traces, and crash reports if the secret landed there.
- Review issuance and verification telemetry for suspicious activity.
- Replace the key in every environment where it was reused.
Prevent replay in production
Replay protection must survive concurrency and multi-instance deployments.
- Use a shared atomic store when your server runs on more than one instance.
- Do not rely on process-local memory for replay protection in distributed deployments.
- Check that zero-amount proof flows have explicit replay protection before you use them for production identity or access control.
Keep local development separate
A local .env file is fine for development if it stays local and out of git. Commit only .env.example with placeholders, use a separate development key, and never reuse production secrets in staging or local environments.