Skip to content

Lightweight modern Python library to add security headers (CSP, HSTS, etc.) to Django, Flask, FastAPI, and more. Secure defaults or fully customizable.

License

Notifications You must be signed in to change notification settings

TypeError/secure

Repository files navigation

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.pyis a lightweight Python library designed to effortlessly addsecurity headersto your web applications, protecting them from common vulnerabilities. Whether you're usingDjango,Flask,FastAPI,or any other popular framework,secure.pyprovides 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.pysupports the following Python web frameworks:

Framework Documentation
aiohttp Integration Guide
Bottle Integration Guide
CherryPy 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
Starlette Integration Guide
Tornado Integration Guide
TurboGears Integration Guide

Features

  • 🔒Secure Headers:Automatically apply headers likeStrict-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 likeFastAPIandStarlette.
  • 📝Enhanced Type Hinting:Complete type annotations for better developer experience.
  • 📚Attribution to Trusted Sources:Implements recommendations from MDN and OWASP.

Requirements

  • Python 3.10or 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 (matchstatement):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 version0.3.0of 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 integratesecure.pyinto your project:

Synchronous Usage

importsecure

# 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 likeFastAPIandStarlettethat support asynchronous operations, use the async method:

importsecure

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

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

Example Usage

importsecure

# 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.pyapplies the following headers when usingwith_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.pyallows you to customize headers such asContent-Security-PolicyandPermissions-Policywith ease:

Content-Security-Policy Example

importsecure

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

# 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; style-src 'unsafe-inline'; img-src 'self' images.example; connect-src 'self' api.example

Permissions-Policy Example

importsecure

# 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

fromfastapiimportFastAPI

fromsecureimportSecure

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


@app.middleware("http")
asyncdefadd_security_headers(request,call_next):
response=awaitcall_next(request)
awaitsecure_headers.set_headers_async(response)
returnresponse


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

Flask

fromflaskimportFlask,Response

fromsecureimportSecure

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


@app.after_request
defadd_security_headers(response:Response):
secure_headers.set_headers(response)
returnresponse


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


if__name__=="__main__":
app.run()

Documentation

For more details, including advanced configurations and integration examples, please visit thefull documentation.


Attribution

This library implements security recommendations from trusted sources:

We have included attribution comments in the source code where appropriate.


Resources


License

This project is licensed under the terms of theMIT License.


Contributing

Contributions are welcome! If you'd like to contribute tosecure.py,please feel free to open an issue or submit a pull request onGitHub.


Changelog

For a detailed list of changes, please refer to theCHANGELOG.


Acknowledgements

We would like to thank the contributors of MDN Web Docs and OWASP Secure Headers Project for their invaluable resources and guidelines that help make the web a safer place.