Triage
Triage is where a raw scan result becomes a decision. TRUSCA has three triage surfaces, each documented in full on its own page: VEX vulnerability triage for CVEs, component approval for conditional-license components, and the build gate that turns those decisions into a pass/fail for CI. This page is the map that ties them together — one place to see how a single finding travels across all three, and, just as important, which decisions actually reach the build gate and which do not.
VEX (Vulnerability Exploitability eXchange) is the standard vocabulary for recording whether a CVE (Common Vulnerabilities and Exposures) genuinely affects your product. A CVE is the public identifier for a known vulnerability.
Engineers and team leads who triage findings and need to understand how their decisions affect CI. Recording a VEX verdict requires developer or higher; disposing a component approval and moving a finding into Suppressed require team_admin.
The three triage surfaces
Each surface owns a different kind of decision. Read the linked page for the full state machine, permissions, and API; this page only shows how they connect.
| Surface | Applies to | Decision recorded | Reaches the build gate? |
|---|---|---|---|
| VEX vulnerability triage | A CVE finding on a component | The finding's exploitability verdict (New → Analyzing → a terminal VEX state) | Yes — excluded states drop out of the Critical-CVE count |
| Component approval | A component carrying a conditional license (LGPL, MPL, EPL, CDDL) | Whether the component's license use is approved (Pending → Under Review → Approved / Rejected) | No — the gate never reads the approval verdict (see the caveat) |
| Build gate | The project's latest successful scan | Pass / Fail for CI | It is the outcome — it reads VEX verdicts and the forbidden license tier |
How a finding flows
A finding enters triage the moment a scan detects it. Its path depends on what kind of finding it is — a vulnerability or a conditional-license component — and the two paths converge only at the build gate.
The two tracks are independent by design:
- A CVE finding is triaged with a VEX verdict. Every finding starts in
New, moves throughAnalyzing, and lands on a terminal state. The three excluded states (Not affected,False positive,Fixed) drop the finding out of the build-gate count. The open states (New,Analyzing,Exploitable) keep it counting, and so doesSuppressed: it records a team decision but does not clear the gate. When many findings share a disposition, bulk-transition them in one action rather than one drawer at a time. - A conditional-license component raises a component approval request in parallel. A reviewer approves or rejects it, and the verdict is recorded for audit — but the gate does not consult it (see below).
Where each decision reaches the build gate
This is the point the three surfaces are most often confused on. The build gate fails a build by default on three conditions:
- at least one open Critical CVE (a Critical finding in any VEX state other than
Not affected,False positiveorFixed; the severity is fixed at Critical and cannot be configured), - at least one component whose license resolves to the
forbiddentier, or - at least one known-malicious package without an active exception. This condition is on unless an operator sets
GATE_MALICIOUS_ENABLEDtofalseor a gate policy turns it off.
Operators can add opt-in conditions (EPSS threshold, CISA KEV, end-of-life components, incomplete scans) and can narrow condition 1 to reachable findings; all of them are off by default.
VEX triage feeds condition 1 directly: moving a finding to an excluded state removes it from the count on the next scan. Component approval feeds none of the conditions.
Component approval does not gate the build
A Rejected component approval does not block the build. The gate evaluates the forbidden license tier only (apps/backend/services/policy_gate.py); it never reads the approval verdict. A rejected component still classifies as conditional on the next scan, and the build proceeds. See the Rejected verdict caveat for the full explanation and the manual follow-up (remove the dependency, or escalate the license to forbidden).
To make a license actually block CI, change its tier rather than its approval verdict — a team can promote a license to forbidden at runtime through a license policy, no redeploy required. To make a non-Critical CVE block CI, add the EPSS build-gate dimension.
The gate always reflects the project's latest successful scan. A triage decision you record now shows in the UI immediately but only changes the gate verdict on the next scan. If a scan was already running when you triaged, that scan still carries the prior state — trigger a new scan to re-evaluate.
Verify it worked
Walk one finding of each kind through its surface and confirm the gate reads the VEX track but not the approval track.
- On the Vulnerabilities tab, move an open Critical CVE to
Not affected. The status badge updates immediately (the same transition the VEX harness covers below). On the next scan, the build-gate Critical-CVE count drops by one.
- The VEX status badge reflects the new state without a page reload.
- Reject a conditional-license component's approval, then re-scan. The build gate verdict is unchanged — confirming approval does not gate — while the Approvals queue and audit log both record the Rejected verdict.
Troubleshooting
A rejected component did not block CI
By design — component approval never reaches the gate. See Component approval does not gate the build. Block it by promoting the license to forbidden via a license policy, or remove the dependency.
A suppressed CVE still counts in the gate
By design. Suppressed is not an excluded state, so a suppressed Critical CVE keeps failing the gate. Only Not affected, False positive and Fixed take a finding out of the count. If one of those is true for the finding, record it instead. The gate also reflects the latest successful scan, so a verdict recorded after that scan applies only on the next one: trigger a new scan, then re-check the gate. See the VEX state machine.
A non-Critical CVE I care about never fails the build
By default the only CVE condition is Critical severity (forbidden licenses and known-malicious packages are the other two). Add the EPSS dimension so a high-probability CVE fails regardless of severity. See Gate the build on EPSS.
See also
- Vulnerabilities — the full VEX state machine, severity model, and bulk-transition
- Approvals — the component approval workflow and the Rejected-verdict caveat
- GitHub Actions — wiring the build gate into CI
- License policies — change a license tier so it actually gates