SkillAgentSearch skills...

Secure

Modern Python library for HTTP security headers (CSP, HSTS, etc.) with secure defaults and presets for Shiny, FastAPI, Django, Flask, and other ASGI/WSGI apps.

Install / Use

/learn @TypeError/Secure

README

secure

A small, focused library for adding modern security headers to Python web applications.

PyPI Version Python Versions License GitHub Stars


Introduction

Security headers are one of the simplest ways to raise the security bar for a web application, but they are often applied inconsistently across frameworks and deployments.

secure gives you a single, modern, well typed API for configuring and applying HTTP security headers in Python. It focuses on:

  • Good defaults that are safe to adopt.
  • A small, explicit API instead of a large framework.
  • Support for both synchronous and asynchronous response objects.
  • Framework agnostic integration so you can use the same configuration everywhere.

The package is published on PyPI as secure and imported with:

import secure

Why use secure

  • Apply essential security headers with a few lines of code.
  • Share one configuration across multiple frameworks and applications.
  • Start from secure presets, then customize as your needs grow.
  • Keep header logic out of your views and handlers.
  • Use one library for FastAPI, Starlette, Flask, Django, and more.
  • Rely on modern Python 3.10+ features and full type hints for better editor support.

If you want your app to ship with a strong security baseline without pulling in a heavyweight dependency, secure is designed for you.


Supported frameworks

secure integrates with a range of popular Python web frameworks. The core API is framework independent, and each framework uses the same Secure object and methods.

| Framework | Documentation | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | aiohttp | Integration Guide | | Bottle | Integration Guide | | CherryPy | Integration Guide | | Dash | Integration Guide | | Django | Integration Guide | | Falcon | Integration Guide | | FastAPI | Integration Guide | | Flask | Integration Guide | | Masonite | Integration Guide | | Morepath | Integration Guide | | Pyramid | Integration Guide | | Quart | Integration Guide | | Responder | Integration Guide | | Sanic | Integration Guide | | Shiny | Integration Guide | | Starlette | Integration Guide | | Tornado | Integration Guide | | TurboGears | Integration Guide |


Features

  • Secure headers
    Apply headers like Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, and more.

  • Presets with secure defaults
    Start from opinionated presets like Preset.BASIC and Preset.STRICT, then customize as needed.

  • Policy builders
    Compose complex policies such as CSP and Permissions Policy through a fluent API.

  • Framework agnostic
    Works with sync and async response objects and does not depend on any single framework.

  • Zero external dependencies
    Easy to audit and suitable for security sensitive environments.

  • Modern Python design
    Uses Python 3.10+ features and full type hints so your editor and type checker can help you.


Requirements

  • Python 3.10 or higher

    secure targets modern Python and is currently tested on Python 3.10 through 3.13.

    It uses features introduced in Python 3.10, including:

    • Union type operator (|) for cleaner type annotations.
    • Structural pattern matching (match).
    • Improved typing and annotations.
    • functools.cached_property for efficient lazy computation.

    If you need support for Python 3.6 through 3.9, use version 0.3.0 of the library.

  • Dependencies

    This library has no external dependencies outside of the Python standard library.


Installation

You can install secure with your preferred Python package manager.

Using uv

uv add secure

Using pip

pip install secure

Quick start

The core entry point is the Secure class. A typical simple setup looks like this:

import secure

secure_headers = secure.Secure.with_default_headers()

# For a synchronous framework
secure_headers.set_headers(response)

# For an asynchronous framework
await secure_headers.set_headers_async(response)

Secure.with_default_headers() is equivalent to Secure.from_preset(Preset.BALANCED), the recommended default profile.

set_headers and set_headers_async both operate on a response object that either:

  • Exposes a set_header(name, value) method, or
  • Exposes a mutable headers mapping that supports item assignment.

If your framework uses a different contract, see the framework specific guides or use header_items() to apply headers manually.

Middleware

secure.middleware re-exports SecureWSGIMiddleware and SecureASGIMiddleware. Each middleware accepts a Secure instance (defaulting to Secure.with_default_headers()), overwrites headers by default, and only appends duplicates when a normalized name is included in multi_ok (the default secure.MULTI_OK includes Content-Security-Policy).

WSGI (Flask + Django)

Wrap any WSGI stack with SecureWSGIMiddleware, and pass a configured Secure instance if you need a custom CSP or additional headers.

from flask import Flask
from secure import Secure
from secure.middleware import SecureWSGIMiddleware

secure_headers = Secure.with_default_headers()
app = Flask(__name__)
app.wsgi_app = SecureWSGIMiddleware(app.wsgi_app, secure=secure_headers)

For Django, apply the headers through a middleware class since Django’s middleware pipeline wraps requests and responses rather than the raw WSGI callable:

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

Register the class in your MIDDLEWARE setting to enforce security headers on every response.

ASGI (FastAPI + Shiny for Python)

SecureASGIMiddleware modifies only HTTP scopes (WebSocket messages pass through untouched). Mount it manually or via FastAPI’s add_middleware, and pass any Secure instance if you need to adjust the defaults.

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

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

If you need to tailor the CSP, build a custom Secure instance before wiring the middleware:

from secure import ContentSecurityPolicy

secure_headers = Secure(
    csp=ContentSecurityPolicy().default_src("'self'").script_src("https://trusted.cdn")
)
app = SecureASGIMiddleware(app, secure=secure_headers)

Shiny for Python apps can be wrapped in the same way:

from shiny import App
from secure import Secure
from secure.middleware import SecureASGIMiddleware

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

Customizing multi_ok

Pass the multi_ok argument to eithe

View on GitHub
GitHub Stars975
CategoryContent
Updated25d ago
Forks29

Languages

Python

Security Score

100/100

Audited on Mar 2, 2026

No findings