Give AlbumentationsX a star on GitHub — it powers this leaderboard

Star on GitHub

secure

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

Rank: #3524Downloads: 1,375,710 (30 days)Stars: 974Forks: 29

Description

secure.py

A simple, yet powerful way to secure your Python web applications across multiple frameworks.

PyPI Version Python Versions Ruff Downloads License GitHub Stars

Introduction

In today's web landscape, security is paramount. secure.py is a lightweight Python library designed to effortlessly add security headers to your web applications, protecting them from common vulnerabilities. Whether you're using Django, Flask, FastAPI, or any other popular framework, secure.py provides a unified API to enhance your application's security posture.


Why Use secure.py?

  • 🔒 Apply Essential Security Headers: Implement headers like CSP, HSTS, and more with minimal effort.
  • 🛠️ Consistent API Across Frameworks: A unified approach for different web frameworks.
  • ⚙️ Customizable with Secure Defaults: Start secure out-of-the-box and customize as needed.
  • 🚀 Easy Integration: Compatible with Python's most-used frameworks.
  • 🐍 Modern Pythonic Design: Leverages Python 3.10+ features for cleaner and more efficient code.

Supported Frameworks

secure.py supports the following Python web frameworks:

FrameworkDocumentation
aiohttpIntegration Guide
BottleIntegration Guide
CherryPyIntegration Guide
DjangoIntegration Guide
FalconIntegration Guide
FastAPIIntegration Guide
FlaskIntegration Guide
MasoniteIntegration Guide
MorepathIntegration Guide
PyramidIntegration Guide
QuartIntegration Guide
ResponderIntegration Guide
SanicIntegration Guide
StarletteIntegration Guide
TornadoIntegration Guide
TurboGearsIntegration Guide

Features

  • 🔒 Secure Headers: Automatically apply headers like Strict-Transport-Security, X-Frame-Options, and more.
  • 🛠️ Customizable Policies: Flexibly build your own security policies using method chaining.
  • 🌐 Framework Integration: Compatible with various frameworks, ensuring cross-compatibility.
  • 🚀 No External Dependencies: Lightweight and easy to include in any project.
  • 🧩 Easy to Use: Integrate security headers in just a few lines of code.
  • Asynchronous Support: Async support for modern frameworks like FastAPI and Starlette.
  • 📝 Enhanced Type Hinting: Complete type annotations for better developer experience.
  • 📚 Attribution to Trusted Sources: Implements recommendations from MDN and OWASP.

Requirements

  • Python 3.10 or higher

    This library leverages modern Python features introduced in Python 3.10 and 3.11, such as:

    • Union Type Operator (|): Simplifies type annotations.
    • Structural Pattern Matching (match statement): Enhances control flow.
    • Improved Type Hinting and Annotations: Provides better code clarity and maintenance.
    • cached_property: Optimize memory usage and performance.

    Note: If you're using an older version of Python (3.6 to 3.9), please use version 0.3.0 of this library, which maintains compatibility with those versions.

  • Dependencies

    This library has no external dependencies outside of the Python Standard Library.


Installation

You can install secure.py using pip, pipenv, or poetry:

pip:

pip install secure

Pipenv:

pipenv install secure

Poetry:

poetry add secure

Getting Started

Once installed, you can quickly integrate secure.py into your project:

Synchronous Usage

import secure

# Initialize secure headers with default settings
secure_headers = secure.Secure.with_default_headers()

# Apply the headers to your framework response object
secure_headers.set_headers(response)

Asynchronous Usage

For frameworks like FastAPI and Starlette that support asynchronous operations, use the async method:

import secure

# Initialize secure headers with default settings
secure_headers = secure.Secure.with_default_headers()

# Apply the headers asynchronously to your framework response object
await secure_headers.set_headers_async(response)

Example Usage

import secure

# Create a Secure instance with default headers
secure_headers = secure.Secure.with_default_headers()

# Apply default secure headers to a response object
secure_headers.set_headers(response)

Default Secure Headers

By default, secure.py applies the following headers when using with_default_headers():

Cache-Control: no-store
Cross-Origin-Opener-Policy: same-origin
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'
Strict-Transport-Security: max-age=31536000
Permissions-Policy: geolocation=(), microphone=(), camera=()
Referrer-Policy: strict-origin-when-cross-origin
Server:
X-Content-Type-Options: nosniff

Policy Builders

secure.py allows you to customize headers such as Content-Security-Policy and Permissions-Policy with ease:

Content-Security-Policy Example

import secure

# Build a custom CSP policy
csp = (
    secure.ContentSecurityPolicy()
    .default_src("'self'")
    .script_src("'self'", "cdn.example.com")
    .style_src("'unsafe-inline'")
    .img_src("'self'", "images.example.com")
    .connect_src("'self'", "api.example.com")
)

# Apply it to secure headers
secure_headers = secure.Secure(csp=csp)

Resulting HTTP headers:

Content-Security-Policy: default-src 'self'; script-src 'self' cdn.example.com; style-src 'unsafe-inline'; img-src 'self' images.example.com; connect-src 'self' api.example.com

Permissions-Policy Example

import secure

# Build a custom Permissions Policy
permissions = (
    secure.PermissionsPolicy()
    .geolocation("'self'")
    .camera("'none'")
    .microphone("'none'")
)

# Apply it to secure headers
secure_headers = secure.Secure(permissions=permissions)

Resulting HTTP headers:

Permissions-Policy: geolocation=('self'), camera=('none'), microphone=('none')

Framework Examples

FastAPI

from fastapi import FastAPI

from secure import Secure

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


@app.middleware("http")
async def add_security_headers(request, call_next):
    response = await call_next(request)
    await secure_headers.set_headers_async(response)
    return response


@app.get("/")
def read_root():
    return {"Hello": "World"}

Flask

from flask import Flask, Response

from secure import Secure

app = Flask(__name__)
secure_headers = Secure.with_default_headers()


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


@app.route("/")
def home():
    return "Hello, world"


if __name__ == "__main__":
    app.run()

Documentation

For more details, including advanced configurations and integration examples, please visit the **[full documentation]