Skip to content

Fix dependency CVEs; raise Python floor back to 3.10 - #5

Open
goetchstone wants to merge 1 commit into
mainfrom
security-dependency-audit
Open

Fix dependency CVEs; raise Python floor back to 3.10#5
goetchstone wants to merge 1 commit into
mainfrom
security-dependency-audit

Conversation

@goetchstone

Copy link
Copy Markdown
Owner

pip-audit found real CVEs in the shipped runtime — and traced the worst of them to
my own earlier decision to support Python 3.9.

The 3.9 floor was a mistake

Every patched starlette and python-multipart release requires >=3.10. The
newest 3.9-compatible versions are starlette 0.49.3 (5 advisories) and
python-multipart 0.0.20 (6 advisories) — and python-multipart parses every form
POST this app serves
. Supporting 3.9 meant shipping a credential-handling web app on
knowingly-vulnerable request-handling libraries.

It was also unnecessary: scripts/build_app.sh bundles its own CPython 3.12, so the
supported install never needed the macOS system interpreter.

Changes

  • requires-python back to >=3.10, with a comment stating it's a security floor
    so it doesn't get "helpfully" lowered again. ruff target-versionpy310.
  • Explicit floors on the deps that parse or transport untrusted input:
    python-multipart>=0.0.31, starlette>=1.3.1, cryptography>=50.0.0, h2>=4.4.1.
  • Upgraded the bundled runtime (cryptography 49→50, h2 4.3→4.4.1).
  • Dev venv rebuilt on 3.12 so tests run against the patched stack instead of 3.9's
    frozen, vulnerable resolution.

Both the dev environment and the shipped bundle now audit clean. Suite still
124 green on starlette 1.6 / fastapi 0.141 (a major-version jump, so this was a
genuine regression check, not a formality).

Automation, so it doesn't recur

  • .github/dependabot.yml — weekly pip + github-actions update PRs. Dependabot
    security updates were already enabled on the repo, but with no config there were no
    routine version bumps, so a dependency could sit on a vulnerable-but-unadvised
    release indefinitely.
  • CI gains ruff, bandit, and a separate audit job running pip-audit --strict
    — a newly-disclosed CVE now fails the build even when nothing in the repo changed.

Secret check (public repo)

Verified no .pem / .p8 / config.json / token file has ever been committed. The
only PRIVATE KEY matches in history are form placeholders and the PEM-header
normalizer in config.py. Secret scanning + push protection are on.

🤖 Generated with Claude Code

pip-audit found real CVEs in the shipped runtime, and traced the worst of
them to my own earlier decision to support Python 3.9.

The 3.9 floor was a mistake. Every patched `starlette` and `python-multipart`
release requires >=3.10; the newest 3.9-compatible versions are starlette
0.49.3 (5 advisories) and python-multipart 0.0.20 (6 advisories) — and
python-multipart parses every form POST this app serves. Supporting 3.9 meant
shipping a web app on knowingly-vulnerable request-handling libraries. It was
also unnecessary: scripts/build_app.sh bundles its own CPython 3.12, so the
supported install never needed the system interpreter.

- requires-python back to >=3.10, with a comment explaining it is a SECURITY
  floor so nobody "helpfully" lowers it again. ruff target-version to py310.
- Explicit security floors on the deps that parse/transport untrusted input:
  python-multipart>=0.0.31, starlette>=1.3.1, cryptography>=50.0.0, h2>=4.4.1.
- Upgraded the bundled runtime (cryptography 49->50, h2 4.3->4.4.1). Both the
  dev environment and the shipped bundle now audit clean.
- Dev venv rebuilt on 3.12 so tests run against the patched stack rather than
  3.9's frozen, vulnerable resolution. Suite still 124 green on
  starlette 1.6 / fastapi 0.141.

Automation so this doesn't recur:
- .github/dependabot.yml — weekly pip + github-actions update PRs. Dependabot
  *security* updates were already enabled, but with no config there were no
  routine version bumps.
- CI gains ruff, bandit, and a separate `audit` job running `pip-audit
  --strict`, so a newly-disclosed CVE fails the build even when nothing in the
  repo changed.

Also verified (public repo): no .pem/.p8/config.json/token file has ever been
committed, and the only "PRIVATE KEY" matches in history are form placeholders
and the PEM-header normalizer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant