Skip to main content

Dependabot alerts vs the Trivy gate

GitHub can list dozens of open Dependabot alerts while the Trivy — filesystem vuln scan gate in security.yml is green. On 2026-10-07 it was 55 alerts against a green main. The two do not use different advisory databases: Trivy’s npm, pip, Poetry and uv entries come from the same GitHub Advisory Database (SeveritySource: ghsa in its JSON output). The gap comes from what each one filters out, and every one of the 55 was explained by the rows below.

Why the gate passes while GitHub flags

The fifth row is a configuration bug, now fixed. The classifier matches a manifest or lockfile at any depth, and tests/unit/scripts/test_security_deps_classifier.py checks every lockfile in the tree against it. The Workers’ lockfiles hold nothing but dev dependencies (wrangler, vitest, esbuild). The gate’s report therefore does not list them at all, while Dependabot alerts on every one. The timing row is how main read green while being red. The sharp advisory was published at 13:43Z on 2026-10-06. The Trivy DB that main’s last scan used was built at 13:07Z the same day. Run on a DB downloaded the next morning, the unchanged main failed the gate on sharp in the root and web/starter lockfiles. A green security.yml run says the gate passed against the DB it had at the time, and nothing newer.

Reproduce each side’s view

The gate, exactly as CI runs it. Use a fresh cache volume when the question is “is main clean right now”, because a cached DB is reused until its NextUpdate and will not contain advisories newer than its build:
Roughly what Dependabot sees: the same command with --include-dev-deps added and --severity and --ignore-unfixed removed. GitHub’s own list:
Triage by package, not by alert. One package can carry ten alerts (PyJWT did), and the version you need is the highest first_patched_version across them.

Why Dependabot cannot fix them itself

Dependabot’s security-update job reports conflicting-dependencies when the parent that pulls a vulnerable package pins it to an exact version or a narrow range that excludes the fix. On 2026-10-07 every fixable alert was in that state, because no parent had released a version with the fix. Each one is now carried by an npm overrides entry. An override outlives its reason unless someone removes it, so here is each one with the condition that retires it: Check whether a parent has caught up with npm view <parent> dependencies.<pkg>. The postcss-selector-parser overrides cross a major version. 7.0.0’s one breaking change is that inserting nodes while iterating is now safe. Both builds were compared before and after, and the output was byte for byte the same: the public site’s real stylesheet (70 KB, 68 .prose rules, Tailwind 4 and typography), and Tailwind 3 on web/starter plus an 81-rule battery of selector-heavy variants (group/peer, arbitrary variants, !important, :has, dark). The root sharp: ^0.35.0 override from #2873 was removed in the same change. It existed because next asked for ^0.34.3 and there was no patched 0.34.x. next 16.3 asks for ^0.35.4, so the lockfile reaches 0.35.5 without it.

Open by design

Alerts with no patched release stay open rather than being dismissed. A dismissed alert never reopens, so dismissing one would also stop Dependabot from opening the fix PR on the day a patch ships. The gate ignores them through ignore-unfixed. As of 2026-10-07:
  • nltk (high, src/cofounder_agent/poetry.lock and mcp-server-voice/uv.lock). Pulled in by llama-index-core and pipecat-ai; our code never imports it. The advisory covers model save and load helpers given caller-controlled paths.
  • braces (high, root and web/starter). Reached through micromatch and chokidar in test and build tooling. A denial of service needs an attacker-supplied glob pattern.
  • sprintf-js (medium, root). Reached through argparse in istanbul’s config loader. Needs an attacker-controlled format string.
Dismiss an alert only when its manifest no longer exists (reason inaccurate, with a comment naming the removed file and where the package lives now). Anything with a patched release gets fixed.

Writing the lockfiles

  • npm: write lockfiles with npm 11 through npx -y npm@11 ..., the same major CI and Dependabot use. The host’s npm 10.9 strips every libc field from a lockfile it rewrites. npx -y npm@11 update <pkg> --package-lock-only --ignore-scripts moves a package within its range; npx -y npm@11 install --package-lock-only --ignore-scripts applies a new override, and if the package does not move, follow it with an update of that package. Confirm the diff touches only the target entries, then run npm ci --dry-run under both npm versions.
  • Poetry: from src/cofounder_agent, poetry update <pkg> --lock, then poetry check --lock. Read the diff: Poetry 2.4 has occasionally rewritten the whole lock.
  • uv: from the project directory, uv lock --upgrade-package <pkg>.