feat: the standard's first position on third-party components - #40
Merged
Conversation
The repo had zero mentions of dependabot, CVEs, or vulnerability scanning. Every other
risk in the standard had a written rule; this one had silence — and it is the first
thing a client security review asks about.
Three parts, and the split between the first two is the design:
dependency-gate (ci.yml) blocks what a change INTRODUCES — diff-scoped
dependency-scan.yml reports the standing stock weekly, as an issue
dependabot.yml opens the upgrade PRs, which ride the full merge bar
Diff-scoping is the load-bearing decision. Every other gate measures the diff; a
vulnerability scan naturally measures the repo, so a CVE published overnight against
untouched code would redden every open PR the next morning. Nobody caused it, nobody
can fix it in their branch, and within a fortnight red is an ambient condition rather
than a signal — which costs us not just this gate but the credibility of every other
one. So the gate compares this branch against the target branch and blocks on the
difference; the standing stock becomes an ordinary spec with a human deciding priority.
The seam follows eval_gate: the stack pack declares a command, the CI/CD packs run it.
The contract is one TSV finding per line, so the packs never learn three JSON schemas.
Verified empirically against real published advisories rather than from documentation,
and two of the three findings changed the implementation:
- `dotnet list package --vulnerable` EXITS 0 with a High advisory present. A step
trusting the exit code passes green while shipping a known-vulnerable package —
the same trap already documented for `dotnet test --filter` matching zero tests.
- `npm audit --json` EXITS 1 when it finds anything, aborting the step under
`set -euo pipefail` before jq runs. Two traps, opposite directions; the contract
normalizes both.
- Severity casing differs (`High` vs `high`), so the comparison must be
case-insensitive. Verified necessity, not defensive habit.
`--output-version 1` is pinned because Microsoft documents that a new JSON version
becomes the default when it ships, which would silently change every parsed field.
Python is honestly weaker and says so: pip-audit reports no severity, so that profile
blocks on any newly introduced vulnerability rather than inventing a threshold. Azure
DevOps has no first-party Dependabot — it is a marketplace extension, and installing
one with repo write access is the client's call. Both gaps are written down rather
than papered over.
This gate has a failure mode the others do not: misconfigured, it reports nothing, and
nothing is indistinguishable from clean. It fails silent and green. The shakedown drill
(plant a known-vulnerable package, watch it go red) is the only proof it is wired, and
the operator guides say so in those words.
Also reconciles the required-status-check lists in the operator guides, which had
already drifted — they named five contexts where the ruleset requires nine.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #11 (with #39, which this stacks on — review that first).
The repo had zero mentions of dependabot, CVEs, or vulnerability scanning. Every other risk in the standard had a written rule; this one had silence — and it is the first thing a client security review asks about.
Three parts
dependency-gate(job inci.yml)dependency-scan.ymldependabot.ymlDiff-scoping is the load-bearing decision. Every other gate measures the diff; a vulnerability scan naturally measures the repo. Blocking that way means a CVE published overnight against untouched code reddens every open PR the next morning — nobody caused it, nobody can fix it in their branch, and within a fortnight red is ambient rather than a signal. That costs not just this gate but the credibility of every other one.
The seam follows
eval_gate: the stack pack declares a command, the CI/CD packs run it. The contract is one TSV finding per line, so the packs never learn three JSON schemas.Verified against real advisories, not documentation
Two of three findings changed the implementation:
dotnet list package --vulnerableexits 0 with a High advisory present. A step trusting the exit code passes green while shipping a known-vulnerable package — the same trap already documented in this repo fordotnet test --filtermatching zero tests.npm audit --jsonexits 1 when it finds anything, aborting the step underset -euo pipefailbefore jq runs. Two traps, opposite directions; the contract normalizes both.Highvshigh), so case-insensitive comparison is a verified necessity, not defensive habit.--output-version 1is pinned because Microsoft documents that a new JSON version becomes the default when it ships, which would silently change every parsed field.Two places this is honestly weaker, and says so
This gate fails differently from the others
Misconfigured, it reports nothing — and nothing is indistinguishable from clean. It fails silent and green where every other rail fails loudly. The shakedown drill (plant a known-vulnerable package, watch it go red) is the only proof it is wired, and all three operator guides say so in those words.
Test plan
python scripts/check_standard.py— no drift;dependency-gateregistered in both platforms' policy filespython -m pytest scripts/tests -q— 46 passingSystem.Net.Http4.3.0;lodash4.17.15 +minimist1.2.0), producing the contract TSV🤖 Generated with Claude Code