Security Headers¶
The SecurityHeadersManager applies HTTP security headers to responses following OWASP best practices. It supports Content Security Policy (CSP), HTTP Strict Transport Security (HSTS), CORS, and a comprehensive set of default headers.
SecurityHeadersManager¶
guard_core.handlers.security_headers_handler.SecurityHeadersManager
¶
agent_handler = None
class-attribute
instance-attribute
¶
cors_config
instance-attribute
¶
csp_config
instance-attribute
¶
custom_headers
instance-attribute
¶
default_headers = {'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'Permissions-Policy': 'geolocation=(), microphone=(), camera=()', 'X-Permitted-Cross-Domain-Policies': 'none', 'X-Download-Options': 'noopen', 'Cross-Origin-Embedder-Policy': 'require-corp', 'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Resource-Policy': 'same-origin'}
class-attribute
instance-attribute
¶
enabled
instance-attribute
¶
headers_cache
instance-attribute
¶
hsts_config
instance-attribute
¶
logger
instance-attribute
¶
redis_handler = None
class-attribute
instance-attribute
¶
configure(*, enabled=True, csp=None, hsts_max_age=None, hsts_include_subdomains=True, hsts_preload=False, frame_options=None, content_type_options=None, xss_protection=None, referrer_policy=None, permissions_policy='UNSET', custom_headers=None, cors_origins=None, cors_allow_credentials=False, cors_allow_methods=None, cors_allow_headers=None)
¶
Source code in guard_core/handlers/security_headers_handler.py
get_cors_headers(origin)
async
¶
Source code in guard_core/handlers/security_headers_handler.py
get_headers(request_path=None)
async
¶
Source code in guard_core/handlers/security_headers_handler.py
initialize_agent(agent_handler)
async
¶
initialize_redis(redis_handler)
async
¶
reset()
async
¶
Source code in guard_core/handlers/security_headers_handler.py
validate_csp_report(report)
async
¶
Source code in guard_core/handlers/security_headers_handler.py
Singleton¶
Thread-safe singleton using threading.Lock for the __new__ double-checked locking pattern. Pre-instantiated as security_headers_manager at module level.
Default Headers¶
Applied to every response when the manager is enabled:
| Header | Default Value |
|---|---|
X-Content-Type-Options |
nosniff |
X-Frame-Options |
SAMEORIGIN |
X-XSS-Protection |
1; mode=block |
Referrer-Policy |
strict-origin-when-cross-origin |
Permissions-Policy |
geolocation=(), microphone=(), camera=() |
X-Permitted-Cross-Domain-Policies |
none |
X-Download-Options |
noopen |
Cross-Origin-Embedder-Policy |
require-corp |
Cross-Origin-Opener-Policy |
same-origin |
Cross-Origin-Resource-Policy |
same-origin |
Configuration¶
The configure() method accepts keyword-only arguments:
security_headers_manager.configure(
enabled=True,
csp={"default-src": ["'self'"], "script-src": ["'self'", "cdn.example.com"]},
hsts_max_age=31536000,
hsts_include_subdomains=True,
hsts_preload=True,
frame_options="DENY",
content_type_options="nosniff",
xss_protection="0",
referrer_policy="no-referrer",
permissions_policy="camera=()",
custom_headers={"X-Custom": "value"},
cors_origins=["https://example.com"],
cors_allow_credentials=True,
cors_allow_methods=["GET", "POST"],
cors_allow_headers=["Authorization"],
)
CSP Configuration¶
CSP directives are stored as dict[str, list[str]] and serialized by _build_csp():
{"default-src": ["'self'"], "script-src": ["'self'", "'nonce-abc123'"]}
# becomes: "default-src 'self'; script-src 'self' 'nonce-abc123'"
Unsafe Sources
The manager logs a warning when CSP directives contain 'unsafe-inline' or 'unsafe-eval'.
HSTS Configuration¶
HSTS is built from a config dictionary:
{"max_age": 31536000, "include_subdomains": True, "preload": True}
# becomes: "max-age=31536000; includeSubDomains; preload"
Preload validation:
max_agemust be >= 31536000 (1 year) for preload. If not, preload is disabled with a warning.includeSubDomainsmust beTruefor preload. If not, it is force-enabled with a warning.
CORS Configuration¶
cors_config = {
"origins": ["https://example.com"],
"allow_credentials": True,
"allow_methods": ["GET", "POST"],
"allow_headers": ["Authorization"],
}
Safety check: If origins contains "*" and allow_credentials is True, credentials are force-disabled and the CORS configuration is blocked. This prevents a known security vulnerability.
Getting Headers¶
Caching: Headers are cached per request path in a TTLCache(maxsize=1000, ttl=300). Cache keys are SHA-256 hashes of normalized paths.
Composition order:
- Default headers (copy)
- CSP header (if configured)
- HSTS header (if configured)
- Custom headers (override any defaults)
CORS Headers¶
Returns an empty dict if:
- CORS is not configured.
- The origin is not in the allowed list.
- Wildcard origin with credentials (security block).
CSP Violation Reporting¶
Validates the structure of a CSP violation report (checks for document-uri, violated-directive, blocked-uri in the csp-report object) and logs the violation.
Header Value Validation¶
All header values pass through _validate_header_value():
- Rejects values containing
\ror\n(HTTP response splitting prevention). - Rejects values longer than 8192 bytes.
- Strips non-printable characters except tab.
Redis Integration¶
Configuration (CSP, HSTS, custom headers) is cached to Redis with a 24-hour TTL. On initialization, the manager attempts to load cached configuration before applying defaults.