fix(deps): clear the orchestrator image's HIGH CVE findings - #295
Conversation
Trivy flagged 33 CRITICAL/HIGH findings on chrisleekr/github-app:1.17.0-orchestrator under the CI flag set. Four distinct causes, four different correct fixes. util-linux (27 findings, CVE-2026-53612/53613/53614) Nine binary packages from one source, all at 2.41-5 in the oven/bun base, all fixed in Debian at 2.41.5-0+deb13u1. Added to the existing targeted --only-upgrade block rather than a blanket apt-get upgrade, so the build stays reproducible and hadolint DL3005 stays quiet. All nine go together: they carry tight inter-package version constraints, so a partial list leaves apt unable to resolve. js-yaml 4.1.1 -> 4.3.1 (CVE-2026-59869, GHSA-5p4m-2wfm-xmqj) ip-address 10.1.0/10.2.0 -> 10.7.0 (CVE-2026-69192) Both transitive, both in range for every declaring consumer, so a plain override collapses them. ip-address had two copies in the image (app/node_modules and app/node_modules/socks/node_modules); the override resolves the lockfile to a single 10.7.0 entry. @anthropic-ai/claude-code 2.1.114 -> 2.1.260 (CVE-2026-55607, arbitrary code execution via git directory confusion, fixed in 2.1.163) The version bump is the symptom. The cause is that the pin was written inline as `npm install -g @anthropic-ai/claude-code@2.1.114`, and renovate.json's custom regex manager only matches `ARG *_VERSION=` lines carrying a `# renovate:` marker. So this pin was invisible to every manager and drifted 146 patch releases behind into a known RCE. Converted to a renovate-managed ARG so it cannot silently rot again. sharp 0.34.5 (GHSA-f88m-g3jw-g9cj): ignored, not bumped Deliberately NOT an override. The fix is sharp 0.35.0 and @huggingface/transformers 4.2.0 (latest) declares `sharp: ^0.34.5`, so forcing 0.35.x would break the declared range. The four inherited libvips CVEs are image-decoding paths, and this repo uses transformers for exactly one thing: the text feature-extraction pipeline in src/orchestrator/embedding.ts. No code path hands an image to libvips, and the module sits behind REVIEW_LEARNINGS_RAG_ENABLED plus a dynamic import. Recorded in .trivyignore.yaml with a reachability statement and expired_at 2026-12-04, per that file's stated policy. Verified by building Dockerfile.orchestrator --target production locally and scanning the result with the exact CI flag set: 0 CRITICAL/HIGH, down from 33. Without the ignorefile exactly one finding remains, the documented sharp entry, so nothing else is masked. Confirmed inside the image: js-yaml 4.3.1, ip-address 10.7.0 (single copy), util-linux family 2.41.5-0+deb13u1, and `claude --version` reporting 2.1.260 exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KUPpJPtxAaHWrBsjytRGyM
|
Warning Review limit reachedNext included review available in 19 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Senior review panel findings (CodeRabbit was rate-limited on this PR, so the panel was the only review gate). Five fixes, two verified against primary sources before acting. js-yaml 4.3.1 -> 4.3.2 4.3.1 is one patch short of clean. GHSA-2883-xcg3-v3hh (HIGH, maxTotalMergeKeys does not limit CPU use for empty merge sources) affects >= 4.0.0 < 4.3.2 and is patched in 4.3.2, confirmed against GitHub's security-advisories API for nodeca/js-yaml. Pinning 4.3.1 would have re-opened the exact orchestrator HIGH gate this PR closes as soon as the advisory syncs into the global DB. 4.3.2 still satisfies both declaring consumers (@kubernetes/client-node and cosmiconfig, each ^4.1.0). claude-code 2.1.260 -> 2.1.236 2.1.260 was published the same day it was pinned. renovate.json enforces a 7-day minimumReleaseAge on patch releases specifically "to catch bad releases before automerge", and that setting governs only Renovate-raised PRs, not a hand-edited pin. This CLI runs under bypassPermissions holding a GitHub installation token, so it is the wrong package to take a same-day release on. 2.1.236 is the vendor's own `stable` dist-tag, 15 days old, and above the 2.1.163 CVE-2026-55607 fix floor. Empty-build-arg guard `--build-arg CLAUDE_CODE_VERSION=` would expand to `npm install -g "@anthropic-ai/claude-code@"`, and npm-package-arg resolves an empty spec to the `*` range, installing whatever is newest with no build failure. The pin would vanish silently. Now validated for exact semver before it reaches npm. Not currently reachable (docker-build.yml passes three fixed build args and no workflow input flows into them), so this is hardening. util-linux comment rationale corrected The old comment claimed a partial list "leaves apt unable to satisfy the tight inter-package version constraints". That is not how --only-upgrade behaves: apt IGNORES names that are not installed and does not error on an omitted one, so trimming the list would silently leave a vulnerable package with no build-time signal. Also corrected "epoch" (the epoch is the `1:` prefix; `+really` is an upstream-version suffix) and the implication that the source builds only nine packages (it builds 33; nine are present in a debian:trixie rootfs). Docs deployment.md said "Node.js 20"; the Dockerfiles add NodeSource node_25.x. Added a Dependency overrides table recording each pin's reason and removal condition, since JSON cannot carry comments. Recorded why no mirrored entry exists in audit-ci.ts (bun audit reports total=0 for this GHSA today) so the asymmetry is deliberate. Restored the null-vs-empty-list note that was lost when .trivyignore.yaml gained its first live entry. Rebuilt and rescanned: 0 CRITICAL/HIGH under the CI flag set. Confirmed in the image: claude 2.1.236, js-yaml 4.3.2, ip-address 10.7.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KUPpJPtxAaHWrBsjytRGyM
Senior review panel round applied (3224d34)CodeRabbit was rate-limited on this PR, so the three-lens review panel was the only review gate. It caught two things worth calling out, both verified against primary sources before acting: 1. 2. The Now pinned to 2.1.236 — the vendor's own Also fixed:
Re-verified after the changes: rebuilt Two findings declined, with reasons:
|
Problem
Trivy flagged 33 CRITICAL/HIGH findings on
chrisleekr/github-app:1.17.0-orchestratorunder the CI flag set (--severity CRITICAL,HIGH --ignore-unfixed). Four distinct causes, four different correct fixes.util-linuxfamily, CVE-2026-53612/53613/53614--only-upgradejs-yaml4.1.1, CVE-2026-59869 + GHSA-5p4m-2wfm-xmqjip-address10.1.0/10.2.0, CVE-2026-69192@anthropic-ai/claude-code2.1.114, CVE-2026-55607sharp0.34.5, GHSA-f88m-g3jw-g9cjThe
claude-codeCVE had a structural causeThe bump is the symptom. The cause: the pin was written inline as
npm install -g @anthropic-ai/claude-code@2.1.114, andrenovate.json's custom regex manager only matchesARG *_VERSION=lines carrying a# renovate:marker. That pin was invisible to every dependency manager and drifted 146 patch releases behind into a known arbitrary-code-execution advisory.Converting it to a renovate-managed ARG is the real fix, so it cannot silently rot again. Both Dockerfiles get the identical change (
check:dockerfile-base-syncenforces the shared prefix byte-for-byte).If you'd rather land the minimum fix version (2.1.163) and let Renovate walk it forward, say so and I'll change it. This is the agent runtime, and 2.1.114 → 2.1.260 is a wide jump.
Why
sharpis ignored rather than bumpedThe fix is sharp 0.35.0, but
@huggingface/transformers@4.2.0(latest, no newer release) declaressharp: ^0.34.5. An override would force a semver-incompatible version.I checked reachability instead. The four inherited CVEs are libvips image-decoding paths. This repo uses transformers for exactly one thing: the text
feature-extractionpipeline insrc/orchestrator/embedding.ts(Xenova/bge-small-en-v1.5, 384-dim). No code path hands an image to libvips, and the module sits behindREVIEW_LEARNINGS_RAG_ENABLEDplus a dynamic import, so a default deploy never loads it.Recorded in
.trivyignore.yamlwith a written reachability statement andexpired_at: 2026-12-04, exactly as that file's own POLICY block requires. Scoped withpaths:to the one file Trivy flagged, so a future vulnerable copy elsewhere still trips the gate.util-linux: why all nine packagesNine binary packages built from one source, all at
2.41-5inoven/bun:1.3.14, all fixed at2.41.5-0+deb13u1. They carry tight inter-package version constraints, so upgrading a subset leaves apt unable to resolve.loginis in the list because Debian ships it from the util-linux source under a+reallyepoch. Added to the existing targeted--only-upgradeblock rather than a blanketapt-get upgrade, keeping the build reproducible and hadolint DL3005 quiet.Verification
Built
Dockerfile.orchestrator --target productionlocally and scanned with the exact CI flag set:sharpentry. Nothing else is masked.js-yaml4.3.1,ip-address10.7.0 (single copy — the nestedsocks/node_modules/ip-addresscollapsed),util-linuxfamily all2.41.5-0+deb13u1,claude --version→2.1.260exit 0.Gates: typecheck 0 errors, lint 0 errors (621 pre-existing warnings),
audit:ci0 advisories, Prettier clean,check:dockerfile-base-sync/check:docs-versions/check:docs-citations/check:no-em-dashesall OK.Test suite with local Postgres + Valkey up: 211 files passed, 0 assertion failures. The 2 non-passing files (
test/integration/repo-knowledge,test/integration/review-learnings) areskipIf(sql === null)environment skips; I verified they skip identically on unmodifiedmain(13 skip / 17 skip, 0 fail), so they are pre-existing and unrelated.Note on the npm postinstall warning
The build logs
npm warn install-scripts @anthropic-ai/claude-code@2.1.260 (postinstall: node install.cjs)— npm 11 blocks global install scripts by default. This is pre-existing (identical on the shipped 1.17.0 image) and benign:claude --versionworks in both. Flagging it because it is visible in the build output, not because this PR changed it.🤖 Generated with Claude Code
https://claude.ai/code/session_01KUPpJPtxAaHWrBsjytRGyM