You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] fastapi-guard declares no lower bound on guard-core, so a wrapper upgrade can leave the core behind #120
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.
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.
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.
Activity
github-actions commentedon Aug 25, 2026
Thanks for opening your first issue on fastapi-guard!
To help us triage quickly, please make sure your report includes:
python --version && uv --version>=3.10,<3.15) and which version you're onpip show fastapi guard-core fastapi-guard(or equivalent) so we can see installed versionsA few pointers:
Thanks again — a maintainer will be with you soon.
rennf93 commentedon Aug 25, 2026
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__.pyimportscheck_ip_access,check_rate_limit_by_ipandis_ip_allowedat import time, and 3.12.0 does not export them, soimport guardraisesImportErrorbefore 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.rennf93 commentedon Aug 26, 2026
Shipped in fastapi-guard 7.8.0 (PyPI), merged in #121 (eb5f284).
pyproject.tomlnow declaresguard-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.