Skip to content

Conversation

@cak
Copy link
Member

@cak cak commented Dec 16, 2025

This PR prepares the v2.0.0rc1 release of secure, delivering a redesigned preset model, first-class ASGI/WSGI middleware, updated header directives, and a safer, more explicit header application pipeline.

Summary

  • Introduces Preset.BALANCED as the new recommended default.
  • Redefines Secure.with_default_headers() to map to Preset.BALANCED.
  • Adds framework-agnostic ASGI and WSGI middleware.
  • Expands the public API with header allowlisting, deduplication, and validation helpers.
  • Refreshes documentation with clearer defaults, migration guidance, and error handling.

Breaking changes

  • Presets redesigned:
    • Added Preset.BALANCED (new default).
    • Preset.BASIC targets Helmet.js parity.
    • Preset.STRICT no longer enables HSTS preload by default.
  • Secure.headers is now strict about duplicate header names (case-insensitive).
    • Use header_items() for multi-valued output or resolve duplicates via the pipeline helpers.

Added

  • SecureASGIMiddleware and SecureWSGIMiddleware (re-exported via secure.middleware).
  • Header pipeline helpers:
    • allowlist_headers(...)
    • deduplicate_headers(...)
    • validate_and_normalize_headers(...)
  • Explicit multi-value serialization via header_items().
  • New constants and policy types: MULTI_OK, COMMA_JOIN_OK, DEFAULT_ALLOWED_HEADERS, and related policy enums.
  • Expanded built-in header coverage (CORP, X-DNS-Prefetch-Control, X-Permitted-Cross-Domain-Policies).
  • Project governance files and CI improvements.

Documentation

  • README rewritten into a full integration guide.
  • Detailed preset documentation (BALANCED, BASIC, STRICT).
  • New middleware, validation pipeline, and error-handling sections.
  • Supported frameworks list expanded (now includes Dash and Shiny).
  • Explicit attribution to MDN and the OWASP Secure Headers Project.

Testing & tooling

  • Expanded unit and contract tests.
  • Improved sync/async response integration coverage.
  • Modernized pyproject.toml and Ruff configuration.

Fixes

This is a release candidate. Feedback on preset defaults, middleware ergonomics, and the validation pipeline is especially welcome before the final v2.0.0 release.

cak added 30 commits September 28, 2025 16:09
Use SPDX license metadata, move license-files to [project],
remove deprecated fields, and bump version to 2.0.0.
Fixes issue #38.

Return a read-only Mapping for `headers` by wrapping the built dict in
`types.MappingProxyType` and updating the signature to `Mapping[str, str]`.
Fixes issue #37.

- set_headers: if response.set_header is async and no event loop is running,
  run to completion via asyncio.run(); if a loop is running, raise a clear,
  prescriptive RuntimeError instructing to use `await set_headers_async(response)`
- set_headers: handle “sync-looking but returns awaitable” setters the same way
- set_headers: use headers.update(...) fast-path when available
- set_headers_async: defensively await results from sync-looking setters;
  support mapping-style headers with callable update() and async __setitem__ fallback
Fixes issue #36

- Iterate header_items() in sync/async setters to keep CSP & Set-Cookie.
- Avoid bulk dict.update() and lossy mappings.
- headers() remains strict/immutable to prevent duplicate loss.
Fixes issue #34
- Wrap per-item header operations in try/except; re-raise as HeaderSetError (TypeError, ValueError, AttributeError)
- Support async setters safely (await/asyncio.run); guide callers to async API when an event loop is running
- Move try/except out of loops to satisfy Ruff PERF203; add Awaitable annotation to address ANN001
Fixes issue #33
- Call self._validate_and_normalize_header(...) before every header write
- Reject CR/LF and disallowed control chars; enforce RFC7230 token names
- Works in both set_header(...) and mapping (__setitem__) branches
- Respects optional _strict/_allow_obs_text/_on_invalid if present
- No breaking changes to public API; fix ships in v2.0
Update issue #36 (Lack of Duplicate Header Detection in Secure Clas)

- Move duplicate handling into chainable deduplicate_headers
- Respect MULTI_OK and COMMA_JOIN_OK; preserve stable order
- header_items now only serializes (name, value) pairs
- Drop in-function dedupe and error logic
- Invalidate cached headers mapping after mutation
New allowlist_headers(on_unexpected=raise|drop|warn, allow_extra, allow_x_prefixed) enforces a case-insensitive header allowlist (fixes #35).
cak added 28 commits December 14, 2025 06:18
@cak cak merged commit 8db0179 into main Dec 16, 2025
7 checks passed
@cak cak deleted the release/2.0.0 branch December 16, 2025 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment