| name | analyze-cve-repos |
| description | Analyze CVE reachability against downstream repository forks at version-specific release branches |
When to Use
Use this skill when Phase 2 of the node-cve:triage command needs to determine whether a CVE's vulnerable code path is actually reachable in a Node team repository. Each CVE is analyzed against ALL affected release branches in parallel (one agent per CVE-branch combination). Features can be added, removed, or refactored across releases, so a CVE may be reachable on one version but not affected on another. Analysis targets downstream forks only; if the downstream fork or branch is not found, the CVE is classified as Uncertain.
Prerequisites
- Repository already cloned to
.work/node-cve/repos/<repo-name>-<branch>/ (the triage command clones all repos at the correct branch before spawning parallel analysis agents)
- Network access to GitHub (for CVE data)
Implementation Steps
Step 1: Map component to downstream repository and branch
Analysis must target the release branch corresponding to the affected OpenShift version. The main branch may have newer dependencies or Go versions that mask vulnerabilities present in shipped releases. Analysis must target downstream forks only. If the downstream fork or branch does not exist, classify as Uncertain with note "downstream fork/branch not found" and skip analysis.
Component to repository mapping: Read the component-to-repo table and pscomponent: label mappings from the node-team shared components reference.
Version mapping: Read from the node-team shared version map. For OCP 4.Y, the formula is K8s/CRI-O minor = Y + 13. Use the formula and branch naming conventions to derive the correct release branch for each repo.
If the component does not map to a known repo, classify as Uncertain and skip analysis. If the downstream fork or release branch does not exist, classify as Uncertain with note "downstream fork/branch not found" and skip analysis.
Step 2: Verify repository and branch
The repository should already be cloned at the correct branch to .work/node-cve/repos/<repo-name>-<branch>/ by the triage command before this skill runs. Verify the directory exists and the checked-out branch matches the expected release branch. If the repo directory does not exist, classify as Uncertain and skip analysis.
Step 3: Gather CVE intelligence
Fetch vulnerability details to understand what to look for in the source code:
- Extract the CVE ID from the Jira issue summary.
- Search for vulnerability details from public sources:
- Search the web for the CVE ID to find advisories, affected packages, vulnerable functions, and fixed versions
- Check the Jira issue description and comments for additional context (affected package, vulnerable API, attack vector)
- Build a vulnerability profile:
- Affected package/library: the specific dependency or stdlib package (e.g.,
golang.org/x/net/html, crypto/x509, capnproto.org/go/capnp)
- Vulnerable functions/methods: specific API surface that triggers the vulnerability (e.g.,
html.Parse, x509.ParseCertificate)
- Attack vector: how the vulnerability is exploited (e.g., malicious input, crafted certificate, oversized allocation)
- Fixed version: version where the fix was applied
If vulnerability details cannot be determined, classify as Uncertain with note "insufficient CVE details available".
Step 4: Check dependency presence
For Go repos, check if the vulnerable package is a dependency:
cd .work/node-cve/repos/<repo-name>-<branch>
grep -r "<affected-package>" go.mod go.sum vendor/modules.txt 2>/dev/null
For Rust repos (conmon-rs), check Cargo.toml and Cargo.lock.
For C repos (conmon), check for the affected library in build files, vendored code, or linked libraries.
If the affected package is not present in the dependency tree, classify as Unaffected with high confidence. Continue to next CVE.
Step 5: Analyze source code for reachability
This is the core analysis step. Read the repository source code to determine if the vulnerable code path is actually exercised.
-
Find imports/usage of the affected package:
grep -rn "import.*<affected-package>" .work/node-cve/repos/<repo-name>-<branch>/ --include="*.go" --include="*.rs" --include="*.c" --include="*.h"
grep -rn "<vulnerable-function>" .work/node-cve/repos/<repo-name>-<branch>/ --include="*.go" --include="*.rs" --include="*.c" --include="*.h"
-
Read the files that use the affected package. For each call site:
- Is the vulnerable function called directly?
- Is it called through a wrapper or interface?
- What data flows into the vulnerable function? Is it attacker-controlled (network input, user-supplied files, untrusted certificates) or internal/trusted?
-
Trace the call path from entry points (main, HTTP handlers, gRPC servers, CLI commands) to the vulnerable function. Determine if the path is reachable in normal operation.
-
Check for mitigating controls:
- Input validation or sanitization before the vulnerable function
- Size limits, timeouts, or rate limiting that prevent exploitation
- Feature flags or configuration that disable the vulnerable code path
- Network policies or authentication that restrict access to the attack vector
-
Assess exploitability in context:
- Is the vulnerable function exposed to untrusted input?
- Does the deployment context (OpenShift node, privileged container) increase or decrease risk?
- Are there compensating controls at the platform level?
Step 6: Classify result
Based on the source code analysis:
| Finding | Classification | Confidence |
|---|
| Vulnerable function called with attacker-controlled input, no mitigations | Reachable | High |
| Vulnerable function called, but input is partially validated | Reachable | Medium |
| Vulnerable function called, but only with trusted/internal data | Present but not exploitable | High |
| Package imported but vulnerable function not called | Present but not reachable | High |
| Package not in dependency tree | Unaffected | High |
| Repo too large to fully analyze, or CVE details insufficient | Uncertain | Low |
Step 7: Build evidence summary
Write a concise analysis for the report:
- Which files import/use the affected package (with file paths and line numbers)
- Whether the vulnerable function is called and from where
- The call path from entry point to vulnerable function (if reachable)
- What input reaches the vulnerable function and whether it's attacker-controlled
- Any mitigating controls found
- Recommended action (update dependency, apply patch, accept risk, investigate further)
Save the analysis to .work/node-cve/triage-$(date +%Y-%m-%d)/<CVE-ID>-<branch>-analysis.md.
Return Value
{
"skill": "analyze-cve-repos",
"cve_id": "CVE-2026-32281",
"repo": "https://github.com/openshift/cri-o",
"branch": "release-1.32",
"ocp_version": "4.19",
"classification": "REACHABLE",
"confidence": "HIGH",
"evidence": {
"affected_package": "crypto/x509",
"vulnerable_function": "x509.ParseCertificate",
"call_sites": [
"pkg/server/tls.go:42 - called from TLS handshake path",
"pkg/server/auth.go:118 - called during client cert validation"
],
"call_path": "main -> server.New -> setupTLS -> x509.ParseCertificate",
"input_source": "network (client TLS certificates, attacker-controlled)",
"mitigations": "none found",
"fixed_version": "go1.22.5"
},
"remediation_hint": "Update Go runtime to 1.22.5+. Vulnerable function processes untrusted client certificates during TLS handshake."
}
Error Handling
- Clone failure: log warning, classify CVE as Uncertain, continue to next CVE
- CVE details unavailable: classify as Uncertain with note "could not determine affected package/function"
- Repo too large to fully trace call paths: focus on direct imports and obvious call sites, note incomplete analysis in evidence
- Permission errors: ensure the work directory is writable