Skip to content

fix(deps,security): restore the blocking Trivy filesystem gate to green - #3240

Closed
bdunncompany wants to merge 2 commits into
LanternOps:mainfrom
bdunncompany:fix/nanoid-cve-2026-67213
Closed

fix(deps,security): restore the blocking Trivy filesystem gate to green#3240
bdunncompany wants to merge 2 commits into
LanternOps:mainfrom
bdunncompany:fix/nanoid-cve-2026-67213

Conversation

@bdunncompany

Copy link
Copy Markdown
Collaborator

The blocking Trivy filesystem scan is failing on every PR and will fail main's next security run. It reports 3 HIGH findings; this restores the gate to green.

I hit it on an unrelated compose-only PR (#3238) whose diff is two YAML files and no lockfile, which is what made it obvious the red is repo-wide rather than commit-specific.

Two halves, two commits — take them independently

1. nanoid CVE-2026-67213 — a real fix.

nanoid@3.3.16 is resolved in the tree; the advisory is an infinite loop in customAlphabet, fixed in 3.3.17. The only consumer of the vulnerable copy is @react-navigation/native@7.3.8, which pins it; its sibling @react-navigation/routers@7.6.0 was already on 3.3.17. There was no pnpm.overrides entry for nanoid at all.

The override is range-bounded — nanoid@>=3.0.0 <3.3.17>=3.3.17 <4.0.0 — so it cannot drag a 3.x consumer onto the 5.x/6.x majors also in the tree (5.1.16 and 6.0.0 are both already above their fixed versions and are untouched).

2. image-size CVE-2025-71329 / CVE-2025-71330 — a risk acceptance.

Trivy reports both as affected with an empty Fixed Version, so no override can clear them. Added to .trivyignore with a justification and a removal trigger, per that file's convention.

Reachability is narrow, and I checked rather than assumed: image-size@1.2.1 has exactly one consumer in the tree (metro@0.84.4), and metro is declared only by apps/mobile. No Dockerfile under docker/ builds apps/mobile, and the api image ships only pnpm --filter @breeze/api deploy --prod output — so neither metro nor image-size reaches a runtime container. Both CVEs are DoS via a crafted image buffer, which on this path means a developer's own bundler run over the repo's own assets. Same distinction the existing pnpm block in that file already draws.

This half is a judgement call, not a fix. It is a separate commit so you can drop it and leave the gate red until upstream publishes, if you'd rather.

Verification

Reproduced CI's exact blocking step locally with the CI-pinned Trivy (0.70.0) via trivy fs --scanners vuln --severity HIGH,CRITICAL --exit-code 1:

tree exit findings
main-equivalent (control) 1 3 HIGH — the same 3 CI reported
this branch 0 none

Resolved-tree checks, not just the override target — the trap where an override is added and the scanner stays red:

  • nanoid@3.3.16 no longer appears anywhere in pnpm-lock.yaml
  • @react-navigation/native now resolves 3.3.17
  • after a real install, the only copy on disk is node_modules/.pnpm/nanoid@3.3.17

Lockfile diff is 4 lines, all nanoid. apps/mobile — the only workspace whose tree changed — passes: 31 files, 322 tests, 3 skipped.

One note: .trivyignore is loaded from the working directory, not the scan target. trivy fs /path ignores it; -w /path ... . honours it. The action gets this right in CI (the pnpm block is being applied); it only bit me locally, and it is worth knowing if anyone else reproduces this by hand.

Trivy's blocking filesystem scan started failing on every PR once the
advisory landed: nanoid 3.3.16 is resolved in the tree and CVE-2026-67213 is
an infinite loop in customAlphabet, fixed in 3.3.17 (and 5.1.6).

The only consumer of the vulnerable copy was @react-navigation/native@7.3.8,
which pins `nanoid: 3.3.16`; its sibling @react-navigation/routers@7.6.0 was
already on 3.3.17. There is no pnpm.overrides entry for nanoid, so nothing
lifted it.

Override is range-bounded (`>=3.0.0 <3.3.17` -> `>=3.3.17 <4.0.0`) so it
cannot drag a 3.x consumer onto the 5.x/6.x majors also present in the tree
(5.1.16 and 6.0.0 are both already above their fixed versions and are left
alone).

Verified on the resolved lockfile, not just the override target: nanoid@3.3.16
no longer appears anywhere, @react-navigation/native now resolves 3.3.17, and
the only remaining resolutions are 3.3.17 / 5.1.16 / 6.0.0. Local
`trivy fs --scanners vuln --severity HIGH,CRITICAL` (0.70.0, the CI-pinned
version) reports zero nanoid findings after the change.
CVE-2025-71329 and CVE-2025-71330 are the remaining HIGH findings failing the
blocking Trivy filesystem scan. Trivy reports both as `affected` with an empty
Fixed Version, so unlike the nanoid advisory there is no version to override
to — the gate cannot go green while they are unignored.

image-size@1.2.1 has exactly one consumer in the tree, metro@0.84.4, and metro
is declared only by apps/mobile. No Dockerfile under docker/ builds apps/mobile
and the api image ships only `pnpm --filter @breeze/api deploy --prod` output,
so neither metro nor image-size reaches a runtime container. Both CVEs are DoS
via a crafted image buffer, which on this path means a developer's own bundler
run over the repo's own assets.

Same distinction the existing pnpm block draws: the filesystem scan is flagging
the monorepo lockfile, not a shipped artifact. Entry carries a justification and
a removal trigger per the file's convention.

This half is a risk acceptance rather than a fix — it is a separate commit so it
can be dropped independently of the nanoid override if you would rather leave
the gate red until upstream publishes.
@bdunncompany

Copy link
Copy Markdown
Collaborator Author

main is now red on this. ca6ccb1d8 (the #3237 merge, 02:42Z) re-ran the security workflow and the blocking Trivy filesystem step failed with the same 3 HIGH findings — nanoid CVE-2026-67213 plus the two image-size advisories. #3237 was TypeScript-only and touched no lockfile or manifest, so it did not introduce them; main had simply not re-run since the vulnerability-DB update.

This PR is green on the full gate (53 success, 1 skipped, all four Integration Tests shards) and takes main back with it.

Both halves are separate commits if you only want the first: 07c56b85d is the nanoid override (a real fix), 1a097fd88 is the .trivyignore entry for the two image-size advisories, which have no upstream fixed version. Dropping the second leaves main red until upstream publishes.

@bdunncompany

Copy link
Copy Markdown
Collaborator Author

Superseded by #3241, which is merged — same two-part shape (bounded nanoid override to 3.3.17, .trivyignore for the two unfixable image-size advisories) and main is green on it. Closing this rather than leaving a duplicate in the queue.

One note worth keeping from the local reproduction, since it will come up next time someone verifies a .trivyignore change by hand: Trivy loads .trivyignore from the working directory, not the scan target. docker run ... trivy fs /scan silently reports already-ignored CVEs and looks like the ignore file isn't working; -w /scan ... fs . honours it. The action gets this right in CI, so it only bites local verification.

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