01
Assume the browser is hostile
Paths, query strings, headers, cookies, multipart bodies, redirect targets, and client bundles are all untrusted. Text rendering escapes values, but raw HTML and remote fetching require explicit policies.
- Sanitize rich user HTML with a scoped policy.
- Allowlist remote hosts and block private network ranges for server fetches.
- Never place secrets or authorization decisions in browser code.
02
Secure Actions end to end
Origin validation is not authorization. Combine Origin policy, CSRF strategy, schema validation, session resolution, resource authorization, idempotency, body limits, and safe errors.
- Use a durable atomic idempotency claim for horizontal scale.
- Keep Action responses safe for users and logs detailed only on the server.
- Test malformed inputs, bad origin, duplicate keys, and oversized bodies.
03
Operate with observable controls
Use CSP and other security headers, secret scanning, dependency audit, rate limits, redacted structured logs, health probes, alerting, and a documented rollback path.
- Start complex CSP policy in report-only mode.
- Use a secret manager and rotate credentials.
- Minimize telemetry and define consent, retention, and access policies.
const response = await handleActionRequest(request, transferFunds, {
allowedOrigins: ['https://app.example.com'],
idempotency: durableIdempotencyStore,
})
// transferFunds.authorize must still resolve the session,
// verify the permission, and confirm account ownership.
expect(response.status).toBe(200)PRACTICE LAB
Prove the behavior.
Write a security test matrix covering XSS output, unsafe redirects, CSRF/origin, authorization, session revocation, traversal, body limits, and cached private data.