Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
# --no-deps: requirements.lock is a flat freeze (no hashes); pip
# resolver is disabled via --disable-pip so no network lookup needed.
#
# Five entries, down from 33 at gate introduction. The old list
# Six entries, down from 33 at gate introduction. The old list
# deferred most of its entries to "the upgrade sprint"; #202 was
# that sprint, and the resulting versions reached or passed every
# fix version the baseline recorded, so 31 flags were suppressing
Expand All @@ -63,6 +63,10 @@ jobs:
# CVE-2026-45830/45831/45833), pip-audit's own canonical ID *is* the
# CVE — the PyPA advisory DB has no PYSEC entry for them yet — so
# these three are pip-audit's real output, not an alias regression.
# CVE-2026-49265 (oauthlib, 2026-09-29) arrives only through
# chromadb -> kubernetes -> requests-oauthlib, none of which the
# backend image installs, and it sits in oauthlib's OAuth *server*
# PKCE check, which UKIP never runs (its SSO is an Authlib client).
# See docs/operating/SECURITY_GATES.md §7e for full disposition.
run: >-
pip-audit -r requirements.lock --disable-pip --no-deps
Expand All @@ -71,6 +75,7 @@ jobs:
--ignore-vuln CVE-2026-45830
--ignore-vuln CVE-2026-45831
--ignore-vuln CVE-2026-45833
--ignore-vuln CVE-2026-49265

# ── Frontend dependency audit (blocking; allowlist via wrapper) ─────────
npm-audit:
Expand Down
31 changes: 30 additions & 1 deletion docs/operating/SECURITY_GATES.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ per-advisory disposition.

### 7e. pip-audit baseline (`--ignore-vuln` flags in `.github/workflows/security.yml`)

**5 vulnerability IDs ignored** (down from 33 at gate introduction). Owner:
**6 vulnerability IDs ignored** (down from 33 at gate introduction). Owner:
platform owner. SLA: next dependency-upgrade window (review by 2026-09-30).

The previous baseline deferred most entries to "the upgrade sprint", noting in
Expand Down Expand Up @@ -347,6 +347,35 @@ re-verified by running the tool rather than assumed.
| CVE-2026-45830 | chromadb==1.5.2 | none published | 2026-09-30 |
| CVE-2026-45831 | chromadb==1.5.2 | none published | 2026-09-30 |
| CVE-2026-45833 | chromadb==1.5.2 | none published | 2026-09-30 |
| CVE-2026-49265 | oauthlib==3.3.1 | 4.0.0 (major) | 2026-10-31 |

**2026-09-29 review: oauthlib, CVE-2026-49265 (GHSA-xpv3-w29h-x7cv).** A
timing side channel in `oauthlib`'s PKCE `code_verifier` comparison
(`oauth2/rfc6749/grant_types/authorization_code.py`, CWE-208), fixed in 4.0.0.
It turned every PR red on the day it was published. Ignored, for two
independent reasons:

1. **Not shipped.** `oauthlib` is lock-only, reached only through
`chromadb` -> `kubernetes` -> `requests-oauthlib`. A `pip install --dry-run
--report -r requirements.txt -c requirements.lock` on 2026-09-29 resolved 97
packages without `oauthlib`, `requests-oauthlib`, `kubernetes` or
`chromadb` (run on Python 3.12; the image uses 3.13).
2. **Not reachable.** The flaw is in the authorization *server* verifying a
PKCE verifier. UKIP issues no OAuth authorization codes; its SSO is an
OAuth *client* built on Authlib, and nothing in `backend/` imports
`oauthlib`.

The fix is a major version under a transitive dependency of a package the
image does not install, so it waits for `requests-oauthlib`/`kubernetes` to
accept 4.x rather than being forced into the lock. Review by 2026-10-31.

Re-verified with pip-audit 2.10.1: without ignores it reports the rows above;
with all six flags, `No known vulnerabilities found, 8 ignored`. It also shows
drift for the next review (2026-09-30): pip-audit now emits the three chromadb
findings as `PYSEC-2026-3813/3814/3815`, not the CVE IDs the flags use. The
Comment on lines +372 to +375

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reconcile the baseline with the new audit result

This new verification makes §7e internally contradictory: lines 327–341 still say that the no-ignore run reports exactly five rows, that five vulnerabilities are ignored, and that every entry uses pip-audit's canonical ID, while this paragraph reports six flags/eight ignored findings and confirms that three configured IDs are now aliases. During the next exception review, operators cannot determine which output is the authoritative baseline; update or remove the stale five-entry verification and canonical-ID claim as part of this change.

Useful? React with 👍 / 👎.

flags still hold them, matched through aliases, which is exactly the silent
failure mode described above; switching those three flags to the canonical
IDs belongs to that review.

Note that `chromadb` is a lock-only entry: it constrains dev installs but is not
among the packages the backend image installs (`pip install -r requirements.txt
Expand Down
Loading