Skip to content

3.0.0

Choose a tag to compare

@rennf93 rennf93 released this 27 Apr 07:51
· 61 commits to master since this release
7d7e9fa

Hardening release routing CORS through the security pipeline.

Companion to guard-core 2.2.0 and guard-agent 2.3.0. Closes the audit's preflight-bypass finding for the Flask adapter.

Breaking change — preflight OPTIONS requests are now subject to the security pipeline.

Pipeline / CORS

  • _before_request now runs the security pipeline for every method including OPTIONS. Banned IPs, rate-limited clients, and suspicious patterns apply to preflight just like every other request.
  • Preflight response construction and response-header injection moved to the shared guard_core.sync.handlers.cors_handler.CorsHandler module.
  • Blocked responses now carry CORS headers when the origin is allowed — cross-origin clients see the real status code instead of an opaque CORS error.
  • _after_request injects CORS headers into normal responses.
  • The old _handle_preflight flow is gone; replaced by _attach_cors_to_blocked and _build_flask_preflight_response helpers.

Internal — suppression cleanup

The release-wide no-suppression rule applied here too. Removed:

  • Every [[tool.mypy.overrides]] ignore_missing_imports = true / follow_imports = "skip" / disallow_untyped_decorators = false block. Replaced with proper stubs (django-stubs if needed), inline-typed packages with py.typed (redis, guard-core, guard-agent).
  • Every # type: ignore marker in edited files. Replaced with cast(...), MagicMock(spec=...), or properly typed callbacks.
  • The [tool.uv.sources] guard-core = { path = ..., editable = true } block from committed pyproject.toml — that's per-developer config, not project metadata. Use uv pip install -e ../guard-core after uv sync for local-dev override.

Configuration

  • guard-agent added to dev dependencies. Previously only mentioned in deptry's ignore list, which meant tests exercising agent integration relied on the package being installed by coincidence.

Test coverage

  • 214 tests, 100% line + 100% branch coverage across flaskapi_guard/ (376 statements, 70 branches, 0 missed). Zero warnings under -W error.

Compatibility

  • Python 3.10–3.14.
  • Requires guard-core>=2.2.0 (declared as unconstrained guard-core in pyproject.toml; documented here for upgrade guidance).
  • guard-agent is a dev dependency; runtime usage remains opt-in via SecurityConfig.enable_agent=True.

Migration

Before — explicit preflight bypass behavior assumed:

config = SecurityConfig(enable_cors=True, cors_allow_origins=["https://app.example.com"], ...)
FlaskAPIGuard(app, config)
# Preflights short-circuited inside the extension before any check ran

After — preflight goes through the same checks as every other request:

config = SecurityConfig(
    enable_cors=True,
    cors_allow_origins=["https://app.example.com"],
    cors_allow_methods=["GET", "POST"],
    cors_allow_headers=["X-Custom"],
    cors_allow_credentials=True,
    cors_max_age=600,
)
FlaskAPIGuard(app, config)

The cors_* fields drive everything; CORS is configured purely via SecurityConfig and activates inside the FlaskAPIGuard extension. There is no separate configure_cors entry point.

What's Changed

Full Changelog: 2.2.0...2.3.0