GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - TypeError/secure: Modern Python library for HTTP security headers with safe defaults, configurable presets, and first-class ASGI/WSGI middleware (FastAPI, Django, Flask, Shiny, and more).

BranchesTags
Open more actions menu

Latest commit

 

History

303 Commits
303 Commits

Folders and files

NameName
Last commit message
Last commit date
.github/workflows
.github/workflows
 
 
docs
docs
 
 
secure
secure
 
 
tests
tests
 
 
.gitignore
.gitignore
 
 
CHANGELOG.md
CHANGELOG.md
 
 
CODE_OF_CONDUCT.md
CODE_OF_CONDUCT.md
 
 
CONTRIBUTING.md
CONTRIBUTING.md
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
great-docs.yml
great-docs.yml
 
 
pyproject.toml
pyproject.toml
 
 
uv.lock
uv.lock
 
 

Repository files navigation

secure

PyPI Version Python Versions License

Define HTTP security headers once. Apply them consistently across Python web apps.

secure provides a small, dependency-free API for configuring modern security headers across common Python web frameworks through ASGI middleware, WSGI middleware, or framework response hooks.

Use it when you want to avoid copy-pasted header strings spread across handlers, hooks, and middleware.

secure hex

Quick links: Quick start · Headers · Middleware


Why use secure

Setting headers manually is fine for one endpoint. It gets harder to review when values are copied across routes, response hooks, reverse-proxy settings, and different framework integrations.

secure helps you:

  • Keep one Secure policy object instead of scattered header strings
  • Apply the same policy through ASGI middleware, WSGI middleware, or response hooks
  • Start with practical presets, then customize headers for your application
  • Use builders for complex headers such as Content Security Policy and Permissions Policy
  • Make duplicate handling, header overwrites, and validation explicit

The defaults are a reasonable starting point, not a substitute for application-specific review. Content Security Policy in particular should be adjusted for the scripts, styles, assets, and third-party services your app actually uses.


Installation

uv add secure
# or
pip install secure

Quick start

FastAPI / ASGI middleware

Use middleware when you can attach secure once and cover the whole application.

from fastapi import FastAPI
from secure import Secure
from secure.middleware import SecureASGIMiddleware

app = FastAPI()
secure_headers = Secure.with_default_headers()

app.add_middleware(SecureASGIMiddleware, secure=secure_headers)

Response hooks and handlers

Use the same policy object in framework hooks, middleware callbacks, or handlers that expose a response object with headers support.

from secure import Secure

secure_headers = Secure.with_default_headers()

secure_headers.set_headers(response)
# or
await secure_headers.set_headers_async(response)

Secure.with_default_headers() maps to Preset.BALANCED, a practical default designed to be customized.


What headers are applied by default

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
Content-Security-Policy: default-src 'self'; base-uri 'self'; font-src 'self' https: data:; form-action 'self'; frame-ancestors 'self'; img-src 'self' data:; object-src 'none'; script-src 'self'; script-src-attr 'none'; style-src 'self' https: 'unsafe-inline'; upgrade-insecure-requests
Strict-Transport-Security: max-age=31536000; includeSubDomains
Permissions-Policy: geolocation=(), microphone=(), camera=()
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

This preset reflects modern browser guidance from MDN and OWASP. It reduces cross-origin risk, prevents MIME sniffing, and provides a conservative Content Security Policy you can extend.

The default CSP avoids unsafe script execution by default, but CSP is context-sensitive. Interactive apps, dashboards, CDNs, analytics, embedded content, or other third-party integrations may require additional configuration.


Presets

from secure import Preset, Secure

Secure.from_preset(Preset.BALANCED)
Secure.from_preset(Preset.BASIC)
Secure.from_preset(Preset.STRICT)
  • BALANCED: practical default for many applications
  • BASIC: Helmet-style compatibility
  • STRICT: tighter CSP and isolation

Start with BALANCED, review the generated headers, and move stricter only when needed.


Middleware

secure provides both ASGI and WSGI middleware.

  • Overwrites headers by default
  • Allows controlled duplication via multi_ok
  • Only modifies HTTP responses in ASGI apps

ASGI

from secure import Secure
from secure.middleware import SecureASGIMiddleware

secure_headers = Secure.with_default_headers()
app = SecureASGIMiddleware(app, secure=secure_headers)

WSGI

from secure import Secure
from secure.middleware import SecureWSGIMiddleware

secure_headers = Secure.with_default_headers()
app = SecureWSGIMiddleware(app, secure=secure_headers)

Django example

from secure import Secure

class SecureHeadersMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.secure = Secure.with_default_headers()

    def __call__(self, request):
        response = self.get_response(request)
        self.secure.set_headers(response)
        return response

Framework integration examples

These examples show common integration paths. See the full framework integration guide for additional frameworks and notes about first-class middleware versus minimal fallback examples.

FastAPI

from secure.middleware import SecureASGIMiddleware

app.add_middleware(SecureASGIMiddleware, secure=secure_headers)

Flask

@app.after_request
def add_security_headers(response):
    secure_headers.set_headers(response)
    return response

Shiny for Python

from shiny import App
from secure.middleware import SecureASGIMiddleware

app = SecureASGIMiddleware(App(), secure=secure_headers)

Interactive apps often need CSP configuration for their script, style, and asset loading patterns.


Policy builders

Content Security Policy

from secure.headers import ContentSecurityPolicy

csp = (
    ContentSecurityPolicy()
    .default_src("'self'")
    .script_src("'self'", "cdn.example.com")
)

Permissions Policy

from secure.headers import PermissionsPolicy

permissions = (
    PermissionsPolicy()
    .geolocation("'self'")
    .camera("'none'")
)

Header pipeline and validation

Use the optional pipeline when you need stricter control:

secure_headers = (
    Secure.with_default_headers()
    .allowlist_headers(...)
    .deduplicate_headers(...)
    .validate_and_normalize_headers(...)
)

This makes header allowlists, deduplication, normalization, and validation explicit instead of leaving those choices spread across application code.


Requirements

  • Python 3.10+
  • No external dependencies

Documentation

Read the full documentation.


Learn more

  • MDN HTTP Headers
  • OWASP Secure Headers Project

License

MIT License


Contributing

Issues and pull requests are welcome.


Acknowledgements

Built using guidance from MDN and OWASP secure headers recommendations.

About

Modern Python library for HTTP security headers with safe defaults, configurable presets, and first-class ASGI/WSGI middleware (FastAPI, Django, Flask, Shiny, and more).

typeerror.com/secure/

Topics

asgicontent-security-policydjangofastapiflaskhttp-headerspythonsecuritysecurity-headersshinystrict-transport-securityweb-securitywsgi

Resources

Readme
MIT license

Code of conduct

Code of conduct

Contributing

Contributing
Activity
Custom properties

Stars

1.1k stars

Watchers

14 watching

Forks

36 forks
Report repository

Releases

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.