CI dependency audit: gunicorn and psycopg, which only the image installs, are never audited #583

Closed
opened 2026-10-01 10:47:49 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, comparing the audited export of the lock file with the extras the image installs.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at .forgejo/workflows/ci.yml:303-308: the step gained --ignore-vuln CVE-2026-49265 (#323), and the export is unchanged. tests/test_security_audit.py, added with #323, already reads this step and could hold the test below.

The security job exports the lock with uv export --no-emit-project --all-groups, without --all-extras, so optional dependencies are left out of what pip-audit reads. The image installs --extra server --extra postgres, so gunicorn, the HTTP server in every container, and psycopg/psycopg-binary are never audited, although SECURITY.md promises that "every locked dependency" is audited on every push and every Monday.

  • Where: .forgejo/workflows/ci.yml:295-299 (the export and the pip-audit call); docker/Dockerfile:89 and :94 (--extra server --extra postgres); SECURITY.md:36-38 and :45-48; docs/THREAT-MODEL.md:102.
  • What happens: exporting the snapshot's lock both ways and comparing them shows that the audited set lacks exactly gunicorn==26.2.0, psycopg==3.3.5 and psycopg-binary==3.3.5. When an advisory is published for one of them, the weekly audit stays green. The image scan would see the package, but it runs only when an image is built (a push to main or a release) and stops only on fixable HIGH or CRITICAL findings, so in a quiet week, or for a MEDIUM advisory, nobody is told and the disclosure process in SECURITY.md never starts.
  • Why it matters: the internet-facing server is the dependency whose advisories matter most, and it is the one the weekly watch cannot see.
  • Fix: add --all-extras to the export in ci.yml (or name --extra server --extra postgres --extra chromium), so the audit covers what the image and the optional renderer install.

Done when

  • A test in tests/test_image_build.py reads the audit step in .forgejo/workflows/ci.yml and asserts that its uv export names --all-extras, or every extra the Dockerfile's uv sync names; it fails today.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, comparing the audited export of the lock file with the extras the image installs. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `.forgejo/workflows/ci.yml:303-308`: the step gained `--ignore-vuln CVE-2026-49265` (#323), and the export is unchanged. `tests/test_security_audit.py`, added with #323, already reads this step and could hold the test below. The `security` job exports the lock with `uv export --no-emit-project --all-groups`, without `--all-extras`, so optional dependencies are left out of what `pip-audit` reads. The image installs `--extra server --extra postgres`, so gunicorn, the HTTP server in every container, and `psycopg`/`psycopg-binary` are never audited, although `SECURITY.md` promises that "every locked dependency" is audited on every push and every Monday. - **Where:** `.forgejo/workflows/ci.yml:295-299` (the export and the `pip-audit` call); `docker/Dockerfile:89` and `:94` (`--extra server --extra postgres`); `SECURITY.md:36-38` and `:45-48`; `docs/THREAT-MODEL.md:102`. - **What happens:** exporting the snapshot's lock both ways and comparing them shows that the audited set lacks exactly `gunicorn==26.2.0`, `psycopg==3.3.5` and `psycopg-binary==3.3.5`. When an advisory is published for one of them, the weekly audit stays green. The image scan would see the package, but it runs only when an image is built (a push to `main` or a release) and stops only on fixable HIGH or CRITICAL findings, so in a quiet week, or for a MEDIUM advisory, nobody is told and the disclosure process in `SECURITY.md` never starts. - **Why it matters:** the internet-facing server is the dependency whose advisories matter most, and it is the one the weekly watch cannot see. - **Fix:** add `--all-extras` to the export in `ci.yml` (or name `--extra server --extra postgres --extra chromium`), so the audit covers what the image and the optional renderer install. ## Done when - A test in `tests/test_image_build.py` reads the audit step in `.forgejo/workflows/ci.yml` and asserts that its `uv export` names `--all-extras`, or every extra the Dockerfile's `uv sync` names; it fails today.
tiagoagueda added this to the 0.5.0 milestone 2026-10-01 10:47:49 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#583
No description provided.