Browser Policy & Security
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
Browser Policy & Security refers to the suite of client-side enforcement mechanisms that govern how a web application interacts with resources, handles cross-origin requests, and protects against common vulnerabilities like XSS. In this project, these policies are critical because their enforcement occurs entirely within the user's browser; if a policy blocks an action, the server receives no notification, resulting in "silent failures" where the application appears broken to the user despite healthy server logs.
The scope of this module covers Content Security Policy (CSP), Cross-Origin Resource Sharing (CORS), SameSite cookie attributes, and secure handling of DOM elements. Proper management requires a balance between strict global security and specific functional exemptions for features like OAuth flows or external media resources.
Sources: BY-STACK/browser-policy.md:3-11, claude-md-snippets/browser-policy.md:3-8
Client-Side Enforcement & Monitoring
Since the browser is the primary enforcer, traditional server-side debugging (like checking for HTTP 403 errors) is ineffective for diagnosing policy violations.
Diagnostic Channels
Developers must rely on two primary channels for identifying blocks:
- Browser Console: The primary location where the browser logs policy violations in real-time.
- CSP Reporting: Utilizing the
report-to(or legacyreport-uri) directive allows the browser to send violation reports to a specified server endpoint, providing the only server-side visibility into client-side blocks.
Sources: BY-STACK/browser-policy.md:14-20, claude-md-snippets/browser-policy.md:21-25
The diagram shows how browser policy violations bypass the server API entirely, appearing only in client-side logs or dedicated report endpoints.
Sources: BY-STACK/browser-policy.md:3-11
Content Security Policy (CSP) Management
CSP is a primary defense-in-depth mechanism. However, overly restrictive global policies often "strangle" legitimate new features.
Directive Conflicts
A common failure occurs when a global 'none' policy is set for a directive (e.g., form-action 'none'), and a new feature later requires that functionality (e.g., adding an OAuth consent form). The browser will block the form submission without any server trace.
| Directive | Risk of Silent Failure | Feature Impact |
|---|---|---|
form-action 'none' | High | Breaks OAuth or HTML forms in SPAs |
SameSite=Strict | High | Blocks cookies during external OAuth redirects |
connect-src 'self' | High | Blocks first-party fetch to new external domains |
frame-ancestors 'none' | Medium | Blocks legitimate third-party embedding |
Sources: BY-STACK/browser-policy.md:28-44, claude-md-snippets/browser-policy.md:3-8
Middleware Implementation
To prevent global policies from breaking specific pages, the recommended approach is Per-Response Overrides via middleware. The middleware should apply global headers only if they are missing, allowing specific handlers to define more permissive (or stricter) policies for their unique needs.
@app.middleware("http")
async def security_headers(request, call_next):
response = await call_next(request) # Handler runs first
for header, value in SECURITY_HEADERS.items():
# Do not overwrite if the page already set a specific policy
response.headers.setdefault(header, value)
Sources: BY-STACK/browser-policy.md:57-63
Warning: Multiple CSP headers are additive. If a middleware runs before the handler or uses append, the browser will enforce the intersection (the most restrictive parts) of all headers, which usually results in a complete block.
Sources: BY-STACK/browser-policy.md:65-70, claude-md-snippets/browser-policy.md:10-14
External Input and Grammar Validation
Security headers are often constructed using external input (e.g., redirect_uri). Incorrectly formatted values can invalidate the entire CSP header, causing the browser to default to the most restrictive state.
Host-Source Validation
When building host-source directives, using urlsplit().netloc is dangerous because it can include userinfo (e.g., user:pass@host), which is invalid in CSP grammar. Similarly, raw IPv6 addresses or non-ASCII domains can invalidate a directive.
Correction Strategy: Use an Allowlist based on the ABNF grammar rather than a Blocklist of characters.
Sources: BY-STACK/browser-policy.md:83-110, claude-md-snippets/browser-policy.md:16-19
import re
# Strict host-source regex following CSP grammar
_CSP_HOST = re.compile(r"[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*\.?")
def validate_csp_host(host):
if not host or not _CSP_HOST.fullmatch(host):
return "" # Omit invalid values rather than pushing broken ones
return host
Sources: BY-STACK/browser-policy.md:118-128
DOM Security & XSS Prevention
Cross-Site Scripting (XSS) is a critical threat when handling external strings in the DOM.
Safe vs. Unsafe Sinks
Directly assigning external data to certain DOM properties creates vulnerabilities.
- Unsafe Sinks:
innerHTML,outerHTML, JSXdangerouslySetInnerHTML, Vuev-html. - Safe Alternatives:
textContent, standard JSX children.
Sanitization Logic
If HTML rendering is strictly required, data must be passed through a sanitizer like DOMPurify immediately before assignment.
// CRITICAL: Sanitize inline at the point of assignment
element.innerHTML = DOMPurify.sanitize(externalValue, {
ALLOWED_TAGS: ["b", "i", "em", "strong"]
});
Sources: bugbot-rules/xss-innerhtml.md:3-23, claude-md-snippets/critical.md:14-17
Testing Policy Enforcement
Standard server-side test clients (e.g., httpx, TestClient) do not enforce browser policies. They will successfully "receive" responses that a real browser would block.
Verification Strategy
- Header Verification: Use server-side tests to verify that the correct headers (CSP, CORS, SameSite) are present in the response.
- Environmental Testing: For critical flows (OAuth, Cross-Origin handoffs), use a real browser driver like Playwright + Chromium. This is the only way to verify that client-side enforcement actually permits the intended behavior.
Sources: TESTING-PATTERNS.md:20-27, claude-md-snippets/testing.md:7-11
Summary
Browser Policy & Security focuses on client-side safety mechanisms that are invisible to server-side logging. The primary risks involve "silent failures" caused by restrictive global CSPs, invalid header grammar from external inputs, and DOM-based XSS. Robust implementation requires per-response header flexibility, strict grammar validation using fullmatch, and end-to-end testing with actual browser engines.
Sources: BY-STACK/browser-policy.md:3-11, TESTING-PATTERNS.md:72-76