feat(detector/vuls2): flatten CPE AND conjunctions to OR in vuls0#2606
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR changes vuls2’s CPE applicability evaluation (walkCPECriteria) to treat NVD AND nodes the same as OR (flattening), aligning vuls0 CPE detection behavior with go-cve-dictionary and avoiding under-reporting for configurations like CVE-2021-28039.
Changes:
- Fold
ANDasORinwalkCPECriteria, removing conjunction-wide tier demotion behavior. - Update docstrings/comments to document the flattening trade-off and scope (CPE detection only).
- Extend/adjust unit tests to cover the
AND→ORflatten behavior and related edge cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| detector/vuls2/vuls2.go | Implements AND-as-OR folding in the CPE walk and updates the explanatory docstring. |
| detector/vuls2/vuls2_test.go | Updates/adds tests and comments to validate the new flattening behavior for AND nodes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
MaineK00n
added a commit
that referenced
this pull request
Jul 15, 2026
…t comment Address Copilot review on #2606: - walkCPECriteria's walk now validates c.Operator (AND/OR) and errors on an unsupported operator instead of silently taking the OR fold, matching walkPkgCriteria's fail-fast behaviour. - Rewrite the "unsatisfied AND" test comment, which still described the old AND-honoured (not-reported) behaviour before contradicting itself with the new folded-as-OR (reported) behaviour. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MaineK00n
added a commit
that referenced
this pull request
Jul 15, 2026
Address Copilot review on #2606: the "unsatisfied AND" test comment mixed "product A"/"product B" prose with "productb leg", which referenced the code's CPE names inconsistently. Use producta/productb throughout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vuls2's CPE walk respected NVD AND applicability nodes, requiring every vulnerable=true leg to have a matching scanned CPE. go-cve-dictionary instead flattens every vulnerable=true CPE in a node into an independently matchable OR list, ignoring the AND/OR operator, and existing users relied on that behaviour. This diverged on CVE-2021-28039, whose NVD config is linux_kernel(x86, 5.9-5.11.3) AND xen:xen -- both marked vulnerable=true. A kernel-only scan matched the kernel leg but not the (absent) xen leg, so the AND vetoed the match and vuls2 under-reported relative to gcd. Fold AND identically to OR in walkCPECriteria: any single satisfied leg carries the node and contributes its matches at its own tier, so a co-required product the scan lacks never vetoes the result. The change is scoped to CPE detection (vuls0) only -- OS-package detection still uses prunePkgCriteria/Affected and is unaffected. The existing prune pass still removes vulnerable=false environment/hardware guards so they can neither be matched nor veto, unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…postConvert Companion postConvert case to "unsatisfied AND": a vulnerable=true leg that accepts, AND a vulnerable=false hardware guard that the scan does not provide. The guard is removed by pruneCPECriteria before the walk, so the CVE is detected via the satisfied leg. This detected even before the AND->OR flatten (the guard never survived pruning), which distinguishes it from the vulnerable=true unsatisfied-leg case that only detects because of the flatten. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…en guard) Adds the AND-shaped counterpart to "cpe no accepted criterion, report nothing": an AND of two vulnerable=true legs where neither accepts. The AND->OR flatten finds no satisfied leg, so nothing is reported. This pins down that folding AND as OR does not spuriously detect when no leg matched -- the negative case the existing AND cases (which all detect) did not cover. The vulnerable=true-both-accept case is already covered by "satisfied AND". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t comment Address Copilot review on #2606: - walkCPECriteria's walk now validates c.Operator (AND/OR) and errors on an unsupported operator instead of silently taking the OR fold, matching walkPkgCriteria's fail-fast behaviour. - Rewrite the "unsatisfied AND" test comment, which still described the old AND-honoured (not-reported) behaviour before contradicting itself with the new folded-as-OR (reported) behaviour. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address Copilot review on #2606: the "unsatisfied AND" test comment mixed "product A"/"product B" prose with "productb leg", which referenced the code's CPE names inconsistently. Use producta/productb throughout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MaineK00n
force-pushed
the
MaineK00n/vuls2-flatten-cpe-and-conjunction
branch
from
July 15, 2026 09:19
fb93168 to
19ba43b
Compare
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.
What
vuls2's CPE walk (
walkCPECriteriaindetector/vuls2/vuls2.go) respected NVDANDapplicability nodes, requiring everyvulnerable=trueleg to have a matching scanned CPE. This PR foldsANDidentically toORin the CPE walk, so any single satisfied leg carries the node.Why
go-cve-dictionary flattens every
vulnerable=trueCPE in an applicability node into an independently matchableORlist, ignoring theAND/ORoperator, and existing users relied on that behaviour.The two backends diverged on CVE-2021-28039, whose NVD config is
linux_kernel (x86, 5.9–5.11.3) AND xen:xen— both markedvulnerable=true:A kernel-only scan matched the kernel leg but not the (absent) Xen leg, so the
ANDvetoed the match and vuls2 under-reported relative to go-cve-dictionary. NVD marking the Xen environmentvulnerable=true(rather than as avulnerable=falseguard, whichpruneCPECriteriaalready strips) is what tripped vuls2's stricterANDhandling.How
walkCPECriteria'swalknow foldsANDthe same asOR: any single satisfied leg carries the node and contributes its matches at its own confidence tier. The conjunction-demotion of exact→vendor:product is dropped (there is no conjunction anymore).prunePkgCriteria/Affectedand is unaffected.vulnerable=falseenvironment/hardware guards and non-CPE criterion types are still removed first, so they can neither be matched nor veto.Trade-off
CVEs with a genuine multi-product
ANDwhere both products arevulnerable=truewill now report each product independently (over-report), matching go-cve-dictionary's long-standing behaviour. This is confined to CPE detection.Tests
Test_walkCPECriteriaandTest_postConvertupdated / extended so the AND four-quadrant is covered:unsatisfied ANDAND with vulnerable=false guardsatisfied ANDAND, report nothingGOEXPERIMENT=jsonv2 go test ./detector/vuls2/is green;gofmtclean.🤖 Generated with Claude Code