Security: clear the open Dependabot and CodeQL alerts - #75
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Security: clear the open Dependabot and CodeQL alerts
This branch closes the standing security alerts against the repository — the Dependabot advisories on locked dependencies and the CodeQL findings in the source. It removes a dependency that was never used (and dragged in unfixable transitive vulnerabilities), refreshes the genuinely vulnerable packages to patched releases, stops error responses from echoing raw exception text, swaps an MD5 cache-key hash for SHA-256, and locks the CI workflows down to read-only token scope. No runtime API changes; the dependency-constraint changes are minimal and called out below.
Vulnerable dependencies patched
The lock file carried a stack of advisories — high-severity ones in
urllib3(decompression bombs, redirect header leakage),python-multipart(arbitrary file write and DoS),aiomysql(arbitrary client file access), andstarlette(Range-header DoS and Host-header path poisoning), plus a long tail of moderate/low issues inidna,python-dotenv,filelock,requests,virtualenv,pygments,pymdown-extensions, andpytest.The fix is a surgical lock refresh: each flagged package was upgraded to its patched release and nothing else was touched.
python-multipart→ 0.0.32,urllib3→ 2.7.0,aiomysql→ 0.3.2,starlette→ 1.2.1,idna→ 3.18,python-dotenv→ 1.2.2,filelock→ 3.29.1,requests→ 2.34.2,virtualenv→ 21.4.2,pygments→ 2.20.0,pymdown-extensions→ 10.21.3,pytest→ 9.0.3.fastapimoved 0.118 → 0.136 as well — not because it was flagged, but because the patched Starlette requires a newer FastAPI, so the bump is a dependency of the Starlette fix rather than an independent upgrade.Why: Keeping
pydantic,sqlalchemy,uvicorn, and the rest pinned at their previous locked versions keeps the security PR reviewable — the only versions that move are the ones a CVE forced. The full test suite passes against the bumpedfastapi/starlette, so the cascade is validated rather than assumed.python-joseremoved entirelypython-josewas a declared runtime dependency, but nothing in the codebase imports it — the admin uses signed cookie sessions, not JWTs. It was pulling inecdsa,pyasn1, andrsatransitively, and those accounted for four alerts on their own, including theecdsaMinerva timing attack on P-256 — which has no fixed release, because the maintainers treat the side channel as a documented limitation rather than a bug.Dropping
python-joseremoves all four of those alerts at once and can't be solved any other way, since no version bump clears the Minerva finding.Why: A version bump was impossible for the unfixable
ecdsaissue, and the dependency earned its keep nowhere — so removing it is both the only fix and a net reduction in attack surface.Error responses no longer leak exception details
Several admin error paths returned the raw exception text to the client — bulk-delete failures, the create/update request handlers, and the relationship data/options endpoints all built responses like
{"message": f"Error loading related data: {str(e)}"}. CodeQL flagged these as information exposure: a stack-deepstr(e)can surface table names, SQL fragments, or internal paths to whoever triggers the error.Each of those handlers now logs the exception server-side (via the module logger, where it's useful for debugging) and returns a fixed, generic message to the client — "Error during deletion.", "Error loading related data.", and so on. The form-rendering paths, which deliberately show validation feedback to the user, are unchanged.
SHA-256 instead of MD5 for memcached keys
The Memcached backend hashes overly long cache keys to stay under Memcached's 250-byte key limit, and it used MD5 to do it. The hash isn't protecting anything — it's a key-shortening device, not a security primitive — but CodeQL flags any MD5 over data as a broken-hash finding, and there's no reason to keep a weak algorithm here.
Both the backend and the test helper that mirrors its key encoding now use SHA-256, with the truncation budget adjusted (
key[:150]plus the 64-char digest) so the composed key still fits comfortably under the limit.CI workflows locked to read-only
The
linting,tests, andtype-checkworkflows declared nopermissionsblock, so they ran with the repository's default — often broader than a test job needs. Each now declarespermissions: contents: readat the top, matching the pattern already used across the sibling projects, so theGITHUB_TOKENin these jobs can do nothing but check out code.Test Plan
Automated
uv run pytest— 345 passed (SQLite; Postgres/MySQL container paths run in CI)uv run ruff check/ruff format --check/uv run mypy crudadmin— all cleanfastapi0.136 /starlette1.2.1Dependencies
python-jose,ecdsa,pyasn1,rsano longer present inuv.lockuv.lockjose/jwtremain anywhere incrudadminortestsError responses
Hashing
Workflows
permissions: contents: readDependencies
python-jose(unused; eliminated theecdsa/pyasn1/rsatransitive chain).aiomysql(mysqlextra)>=0.2.0→>=0.3.0for CVE-2025-62611.pyprojectconstraints; no new dependencies were added.Breaking Changes
python-joseis no longer installed by CRUDAdmin. It was unused, but any downstream code that relied on importingjosetransitively through this package — rather than declaring it directly — will fail to import. The fix on their side is to declarepython-joseas their own dependency.aiomysql>=0.3.0is now required for themysqlextra. Anyone pinned toaiomysql0.2.x must upgrade; 0.3.0 changed howLOAD DATA LOCAL INFILEis configured, which only matters if you use that in your own code.