A lightweight package that adds security headers for Python web frameworks.


Keywords
aiohttp, bottle, cherrypy, django, falcon, fastapi, flask, masonite, pyramid, responder, sanic, starlette, tornado
License
MIT
Install
pip install secure==0.3.0

Documentation

secure.py

image Python 3 image image Build Status

secure.py 🔒 is a lightweight package that adds optional security headers for Python web frameworks.

Supported Python web frameworks

aiohttp, Bottle, CherryPy, Django, Falcon, FastAPI, Flask, hug, Masonite, Pyramid, Quart, Responder, Sanic, Starlette, Tornado

Install

pip:

pip install secure

Pipenv:

pipenv install secure

After installing secure:

import secure

secure_headers = secure.Secure()

Secure Headers

Example

secure_headers.framework(response)

Default HTTP response headers:

strict-transport-security: max-age=63072000; includeSubdomains
x-frame-options: SAMEORIGIN
x-xss-protection: 0
x-content-type-options: nosniff
referrer-policy: no-referrer, strict-origin-when-cross-origin
cache-control: no-store

Policy Builders

Policy Builder Example

Content Security Policy builder:

csp = (
        secure.ContentSecurityPolicy()
        .default_src("'none'")
        .base_uri("'self'")
        .connect_src("'self'", "api.spam.com")
        .frame_src("'none'")
        .img_src("'self'", "static.spam.com")
    )
secure_headers = secure.Secure(csp=csp)

HTTP response headers:

strict-transport-security: max-age=63072000; includeSubdomains
x-frame-options: SAMEORIGIN
x-xss-protection: 0
x-content-type-options: nosniff
referrer-policy: no-referrer, strict-origin-when-cross-origin
cache-control: no-store
content-security-policy: default-src 'none'; base-uri 'self'; connect-src 'self' api.spam.com; frame-src 'none'; img-src 'self' static.spam.com"

Documentation

Please see the full set of documentation at https://secure.readthedocs.io

FastAPI Example

import uvicorn
from fastapi import FastAPI
import secure

app = FastAPI()

server = secure.Server().set("Secure")

csp = (
    secure.ContentSecurityPolicy()
    .default_src("'none'")
    .base_uri("'self'")
    .connect_src("'self'" "api.spam.com")
    .frame_src("'none'")
    .img_src("'self'", "static.spam.com")
)

hsts = secure.StrictTransportSecurity().include_subdomains().preload().max_age(2592000)

referrer = secure.ReferrerPolicy().no_referrer()

permissions_value = (
    secure.PermissionsPolicy().geolocation("self", "'spam.com'").vibrate()
)

cache_value = secure.CacheControl().must_revalidate()

secure_headers = secure.Secure(
    server=server,
    csp=csp,
    hsts=hsts,
    referrer=referrer,
    permissions=permissions_value,
    cache=cache_value,
)


@app.middleware("http")
async def set_secure_headers(request, call_next):
    response = await call_next(request)
    secure_headers.framework.fastapi(response)
    return response


@app.get("/")
async def root():
    return {"message": "Secure"}


if __name__ == "__main__":
    uvicorn.run(app, port=8081, host="localhost")

HTTP response headers:

server: Secure
strict-transport-security: includeSubDomains; preload; max-age=2592000
x-frame-options: SAMEORIGIN
x-xss-protection: 0
x-content-type-options: nosniff
content-security-policy: default-src 'none'; base-uri 'self'; connect-src 'self'api.spam.com; frame-src 'none'; img-src 'self' static.spam.com
referrer-policy: no-referrer
cache-control: must-revalidate
permissions-policy: geolocation=(self 'spam.com'), vibrate=()

Resources