Secure is the public entry point. Configure it once, then reuse it wherever your framework gives you access to the response.
Secure.with_default_headers() is the recommended starting point. It matches Preset.BALANCED.
from secure import Secure
secure_headers = Secure.with_default_headers()You can also choose a preset explicitly:
from secure import Preset, Secure
balanced = Secure.from_preset(Preset.BALANCED)
basic = Secure.from_preset(Preset.BASIC)
strict = Secure.from_preset(Preset.STRICT)Preset.BALANCED: recommended default for most applications.Preset.BASIC: adds legacy and interoperability headers.Preset.STRICT: tighter CSP, disabled caching, and stricter framing rules.
Use set_headers() for synchronous response objects:
from secure import Secure
secure_headers = Secure.with_default_headers()
def add_security_headers(response):
secure_headers.set_headers(response)
return responseUse set_headers_async() in async code or when the response object may expose async setters:
from secure import Secure
secure_headers = Secure.with_default_headers()
async def add_security_headers(response):
await secure_headers.set_headers_async(response)
return responseSecure works with response objects that provide either:
response.set_header(name, value)response.headers[name] = value
If your framework uses a different contract, emit headers manually with header_items().
Presets are the shortest path. When you need more control, pass builder objects into Secure.
from secure import (
ContentSecurityPolicy,
PermissionsPolicy,
Secure,
StrictTransportSecurity,
)
secure_headers = Secure(
csp=(
ContentSecurityPolicy()
.default_src("'self'")
.img_src("'self'", "https://images.example.com")
.script_src("'self'", "https://cdn.example.com")
),
hsts=StrictTransportSecurity().max_age(63072000).include_subdomains(),
permissions=PermissionsPolicy().geolocation().microphone().camera(),
)This keeps the configuration readable while avoiding hand-built header strings.
Most applications do not need this. It is useful when headers are being merged, extended, or generated dynamically and you want validation before emission.
from secure import Secure
secure_headers = (
Secure.with_default_headers()
.allowlist_headers()
.deduplicate_headers()
.validate_and_normalize_headers()
)After validate_and_normalize_headers(), the normalized mapping is available via secure_headers.headers.
Use header_items() when a framework does not expose a supported response interface or when you need ordered header pairs.
from secure import Secure
secure_headers = Secure.with_default_headers()
for name, value in secure_headers.header_items():
response.headers[name] = valueFor framework-specific examples, see Framework Integration.