Skip to content

[BUG] fastapi-guard declares no lower bound on guard-core, so a wrapper upgrade can leave the core behind #120

Closed

Description

@RomanPszonka

Requires-Dist for 7.7.0 is a bare guard-core, with no version specifier at
all — same for fastapi, starlette and uvicorn.

The concrete consequence, hit while upgrading a deployment this morning:
fastapi-guard was bumped to 7.7.0 and the resolver kept guard-core at
3.12.0, because nothing asked it to move. 3.12.0 is the release the
2026-08-25 advisories are filed against, so the upgrade that was supposed to
apply eleven security fixes applied none of them, and neither pip nor uv
said anything.

An application that imports ThreatBanConfig or ip_ban_manager can declare
guard-core itself and pin it, which is what we ended up doing. One that only
imports SecurityMiddleware has no reason to know guard-core exists, and gets
the silent version skew.

Fix: floor it at the release the wrapper actually needs and cap the major —
guard-core>=3.13,<4 — and give the other three runtime dependencies lower
bounds too. Since the two packages are released together, a floor that moves
with each release is the mechanism that makes a fastapi-guard upgrade mean
what people assume it means.



Found while re-checking a private audit against the current release. Verified on fastapi-guard 7.7.0 + guard-core 3.13.0, CPython 3.14.

Activity

  1. github-actions commented on Aug 25, 2026

    @github-actions
    Contributor

    Thanks for opening your first issue on fastapi-guard!

    To help us triage quickly, please make sure your report includes:

    • A clear reproduction (a short FastAPI app or failing test is ideal)
    • Output of python --version && uv --version
    • The Python version range supported (>=3.10,<3.15) and which version you're on
    • pip show fastapi guard-core fastapi-guard (or equivalent) so we can see installed versions
    • Operating system, ASGI server (uvicorn / hypercorn / daphne), and Redis configuration if relevant
    • Logs / tracebacks / middleware ordering details

    A few pointers:

    Thanks again — a maintainer will be with you soon.

  2. rennf93 commented on Aug 25, 2026

    @rennf93
    Member

    Thanks @RomanPszonka for opening the issue! By @rennf93's directive:

    Agreed on the mechanism; we reproduced it with pip (upgrading fastapi-guard alone leaves guard-core at 3.12.0).

    One correction: the result is not silent. guard/__init__.py imports check_ip_access, check_rate_limit_by_ip and is_ip_allowed at import time, and 3.12.0 does not export them, so import guard raises ImportError before the app serves anything. Also, the count is 10 advisories on 2026-08-25, not 11; the eleventh predates that batch and was patched in 3.12.0.

    We kept guard-core unconstrained deliberately, but the floor is the right call: 7.8.0 declares guard-core>=3.14.0, and the floor moves with every lockstep release. No upper cap.

  3. self-assigned this
    on Aug 25, 2026
  4. added
    bugConfirmed defect
    dependenciespyproject.toml or uv.lock
    buildMakefile / Docker / setup.py / packaging
    on Aug 26, 2026
  5. rennf93 commented on Aug 26, 2026

    @rennf93
    Member

    Shipped in fastapi-guard 7.8.0 (PyPI), merged in #121 (eb5f284).

    pyproject.toml now declares guard-core>=3.14.0, a floor only, moved with each lockstep release; the policy is stated in the CHANGELOG. Upgrading fastapi-guard alone now pulls the matching guard-core instead of failing at import.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugConfirmed defectbuildMakefile / Docker / setup.py / packagingdependenciespyproject.toml or uv.lock

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions