Web Security / Advanced: assurance, supply chain, and recovery / Lesson 13
Security headers and Content Security Policy
Treat browser response policy as a reviewed contract with compatibility, rollout, and verification responsibilities.
On this page
Lesson goals
- Explain CSP and complementary response headers without overclaiming.
- Separate report-only observation from enforced behavior.
State which browser capability is being constrained
Response headers can constrain script and resource loading, embedding, MIME interpretation, referrer disclosure, and transport behavior. They complement application controls rather than repairing every unsafe sink or access rule. Define the featureโs legitimate scripts, styles, images, frames, and connections before choosing a policy. A copied strict policy can break the application without explaining what protection is intended. Review the actual response path, including reverse proxies, error pages, redirects, and caches. Displaying header text in a lesson neither configures a server nor proves a browser enforced it. Browser support and deployment context remain part of the claim.
Read a narrowly scoped illustrative policy
The fictional portal permits same-origin default resources, disallows objects, restricts base URL changes, and does not permit embedding. This is not a universal policy for every product. Inline scripts and third-party integrations may require a different reviewed design, commonly involving supported nonce or hash mechanisms. A nonce must meet its documented unpredictability and per-response requirements; a public constant copied from a tutorial is not suitable. frame-ancestors has its own semantics and does not simply inherit every default rule. Keep response policy connected to actual resource needs and test ordinary user flows before enforcement.
Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
These fields describe one hypothetical resource contract and are not installed or sent. They can block legitimate behavior in another app. The example does not generate nonces, test browser support, or establish complete XSS protection.
Distinguish reporting from blocking
A report-only CSP can help observe policy violations without enforcing the corresponding block. It is not proof that an enforced policy would preserve every task, and reports can be incomplete or contain sensitive URL information. Define collection scope, privacy, access, and retention. Investigate legitimate resource needs rather than broadly adding unsafe allowances until the console is quiet. Test negative and positive policy cases in an authorized browser environment. The absence of reports can mean missing collection rather than absence of violations. Keep the selected policy and exact release artifact with the resulting evidence.
Check a stated directive set without emulating a browser
The pure example parses a small fixed policy into a teaching dictionary and checks selected directives. It is deliberately not a complete CSP parser and does not model duplicate directives, browser grammar, precedence, or network enforcement. A real policy should be produced and inspected through maintained framework or server configuration. This local check can catch accidental changes to the displayed classroom record but cannot certify a deployment. Keep policy text, response placement, support assumptions, and actual behavior separate. Never run a real external scanner or alter a configured site merely to validate this example.
policy = "default-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'"
directives = {}
for part in policy.split(";"):
name, *values = part.strip().split()
directives[name] = values
assert directives["object-src"] == ["'none'"]
assert directives["frame-ancestors"] == ["'none'"]
Runs offline on an invented string. It checks two declared values only and sends no header or report. It is not a standards-complete parser or a browser security test.
Review other headers and rollback implications separately
HSTS can strengthen HTTPS use under its documented host scope, but long-lived settings, subdomain inclusion, and preload decisions need operational review and recovery planning. MIME sniffing controls require correct content types, while referrer policy should match privacy and integration needs. Cross-origin isolation features have additional resource and compatibility requirements and are not universal switches to enable blindly. Verify headers on all relevant response classes, not only a successful HTML page. A useful security-header decision explains purpose, legitimate behavior, enforcement evidence, remaining limits, and ownership of changes over time.
Common errors and fixes
Report-only is reported as enforced protection
- Why it happens
- Observation mode is confused with blocking.
- How to fix it
- State the active mode and verify the enforced policy separately.
- Prevent it next time
- Track policy mode with release evidence.
A copied CSP breaks ordinary functionality
- Why it happens
- Resource needs and integration were not reviewed.
- How to fix it
- Define a narrow supported policy and test real user tasks.
- Prevent it next time
- Review additions rather than granting broad exceptions.
No violation reports means no issue
- Why it happens
- Collection completeness is assumed.
- How to fix it
- Verify reporting health and browser coverage.
- Prevent it next time
- Keep missing data distinct from passing behavior.
Check your understanding
1. Why is a nonce shown as a public constant unsuitable for production?
Show worked solution
A nonce mechanism relies on documented freshness and unpredictability within the response policy. A repeated public marker does not provide that property. Use the supported framework mechanism and verify binding between the header and intended resource.
2. A header is correct on the homepage but absent on error responses. What should review do?
Show worked solution
Review the complete response path, middleware order, proxy behavior, and response classes. Verify the intended policy applies where needed without exposing sensitive error content. One successful response does not establish application-wide coverage.
Key takeaways
- Headers constrain specific browser behavior.
- Reporting and enforcement require different evidence.
- Policy changes need compatibility and recovery ownership.