1. Inventory origins, resources, and sensitive responses
List the origins that call each API, the third-party resources every page loads, and which responses contain private data. Header generation is the last step; the inventory determines the policy.
2. Fix caching and publish a reporting contact
Set private or no-store behavior on personalized responses before tuning public asset caching. Publish security.txt early because it does not alter page execution and gives researchers a clear reporting path.
3. Narrow CORS per endpoint
CORS is a browser read-permission policy, not authentication. Allow only origins and methods required by the endpoint, return Vary: Origin when responses differ by origin, and never pair credentialed requests with a wildcard origin.
4. Observe CSP before enforcing it
Begin with Content-Security-Policy-Report-Only, collect violations without including sensitive page data, and remove unnecessary sources. Enforce the smallest proven policy, then tighten it incrementally.
5. Restrict features and verify external assets
Use Permissions-Policy to disable unused powerful features. Add Subresource Integrity only to immutable cross-origin assets with a dependable versioning strategy; otherwise a legitimate upstream change can break the page.
What each header actually controls
| Control | Primary job | Common mistake |
|---|---|---|
| CORS | Which origins may read a response in browsers | Treating it as login or request blocking |
| CSP | Which resources and execution paths a page may use | Enforcing a guessed policy without reports |
| Permissions-Policy | Which browser features a document or iframe may use | Assuming it replaces user permission prompts |
| Cache-Control | Where and how long a response may be stored | Caching personalized responses publicly |
| SRI | Whether a fetched asset matches expected bytes | Hashing an asset that changes at the same URL |