Phase 14: Security + Storage#
Implement Content Security Policy Level 2 to allow pages to declare which sources of content are permitted.
Background#
Depends on: Same-Origin Policy enforcement.
CSP allows a server to specify, via HTTP headers or meta tags, which origins are allowed for scripts, styles, images, fonts, and other resource types. Violations are blocked and optionally reported.
Requirements#
CSP header parsing#
- Parse Content-Security-Policy and Content-Security-Policy-Report-Only HTTP response headers
- Parse CSP from meta http-equiv="Content-Security-Policy" elements
- Support multiple policies (intersection semantics: all must allow)
Directives#
- default-src: fallback for all fetch directives
- script-src: controls script loading and inline script execution
- style-src: controls stylesheet loading and inline styles
- img-src: controls image loading
- font-src: controls font loading
- connect-src: controls fetch/XHR/WebSocket destinations
- frame-src: controls iframe sources
- media-src: controls audio/video sources
- object-src: controls plugin content
- base-uri: restricts base element URLs
- form-action: restricts form submission targets
Source expressions#
- Keyword sources: 'none', 'self', 'unsafe-inline', 'unsafe-eval'
- Nonce sources: 'nonce-'
- Hash sources: 'sha256-', 'sha384-', 'sha512-'
- Host sources: *.example.com, https://example.com, https://example.com:443
- Scheme sources: https:, data:, blob:
Enforcement#
- Before loading any subresource, check if it is allowed by the active CSP
- Block inline scripts unless 'unsafe-inline', a matching nonce, or a matching hash is present
- Block eval() unless 'unsafe-eval' is present
- For report-only policies, allow the resource but log a violation
Integration points#
- New module in crates/browser (e.g., crates/browser/src/csp.rs)
- crates/browser/src/loader.rs: check CSP before fetching subresources
- crates/html: extract CSP from meta tags during tree building
- crates/js: check script-src and 'unsafe-eval' before script execution
Acceptance Criteria#
- CSP headers and meta tags are correctly parsed into policy objects
- default-src fallback works when specific directives are absent
- 'self', host, scheme, nonce, and hash source matching all work correctly
- Inline scripts are blocked unless explicitly allowed
- eval() is blocked unless 'unsafe-eval' is present
- Multiple policies use intersection semantics
- Report-only mode logs but does not block
- cargo clippy --workspace -- -D warnings passes
- cargo test --workspace passes