| name | fix-cve |
| description | Fixes a CVE in nrdot distributions by looking up the CVE details, finding the
installed vulnerable version in the generated go.sum files, adding a Go module
replace directive to all affected manifest.yaml files, then regenerating licenses
and committing the fix.
|
| trigger | /fix-cve |
| type | agent |
| parameters | [{"name":"cve_id","description":"CVE identifier (e.g., CVE-2026-42154)","required":false}] |
| permissions | ["Read","Edit","Bash"] |
Fix CVE Skill
Given a CVE ID, looks up the vulnerability details, finds the vulnerable version
in the generated go.sum files, adds replace directives to all distribution manifests,
regenerates licenses, and commits the fix.
Steps
1. Get CVE IDs
If the user explicitly provided a CVE ID, skip to step 2. Otherwise, use gh api to search for high or crtitical CVEs:
repo=$(git remote get-url origin | sed 's|.*github.com[:/]\(.*\)\.git|\1|')
gh api "repos/$repo/code-scanning/alerts?state=open" | \
jq '[.[] | select(.rule.security_severity_level == "high" or .rule.security_severity_level == "critical") | .rule.id] | unique'
2. Look up the CVE
Use the OSV/NVD API or web search to find:
- The affected Go module path (e.g.,
github.com/prometheus/prometheus)
- The fixed version (e.g.,
v0.311.3)
Useful sources (in order of preference):
https://api.osv.dev/vulnerability/<CVE_ID> — structured JSON with package and fixed version
https://nvd.nist.gov/vuln/detail/<CVE_ID>
- Web search:
<CVE_ID> golang fix version
3. Find the installed vulnerable version
The installed version comes from the go.sum files generated by OCB. Run generate-sources first if the go.sum files don't exist yet:
make generate-sources
Then grep the go.sum files for the affected module:
grep "<module_path>" distributions/*/_build/go.sum | head -5
The version in go.sum is the exact string to use in the replace directive (it may be a pseudo-version like v0.311.2-0.20260409145810-72293ff1d2e0).
Only distributions whose go.sum contains the module need the replace. To be safe, add the replace to all manifests that include it.
4. Check if upstream has already fixed the dependency
Before adding a replace directive, check whether the upstream components that pull in the vulnerable package have already bumped it in their latest release. If they have, a NRDOT version bump would be a cleaner fix.
4a. Find which components directly depend on the vulnerable package
In the _build directory of any affected distribution, use go mod graph to find the direct dependents:
pushd "distributions/nrdot-collector/_build" > /dev/null
go mod graph | grep "@<installed_version>" | grep "<module_path>"
popd > /dev/null
This lists edges in the form parent@version <module_path>@version. Extract the unique parent modules — these are the direct dependents. Focus on any that are opentelemetry-collector-contrib components (e.g., github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver).
4b. Get the latest upstream release tag
gh release list --repo open-telemetry/opentelemetry-collector-contrib --limit 1 --json tagName --jq '.[0].tagName'
4c. Check each dependent component's go.mod in the latest release
For each contrib component identified in step 4a, fetch its go.mod from the latest tag and check whether it still uses the vulnerable version:
curl -s "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector-contrib/<latest_tag>/receiver/prometheusreceiver/go.mod" | grep "<module_path>"
Decision:
- If all dependent components in the latest release have bumped to >=
fixed_version: Inform the user that the vulnerability is already fixed upstream in <latest_tag> and that a NRDOT version bump would resolve it without needing a replace directive. Ask, in a user question prompt, if they want to proceed with the replace anyway as a short-term fix, or stop here. Exit without changes if they choose to stop.
- If any dependent component still uses the vulnerable version in the latest release: Proceed directly to step 5.
5. Add the replace directive
In each affected distributions/*/manifest.yaml, append under replaces::
- <module_path> <installed_version> => <module_path> <fixed_version>
Rules:
- Comment immediately before the replace line
- No severity label in the comment (e.g., don't write "HIGH severity")
- Use the exact pseudo-version string from go.sum as
installed_version
- Ensure
fixed_version has a v prefix
Example result:
replaces:
- github.com/prometheus/prometheus v0.311.2-0.20260409145810-72293ff1d2e0 => github.com/prometheus/prometheus v0.311.3
6. Commit and push a branch
Create a branch:
- Branch title:
$developer/fix-<CVE_ID>
- Stage:
distributions/*/manifest.yaml distributions/*/THIRD_PARTY_NOTICES.md
- Message:
"fix: <CVE_ID>".
7. Create and push a changelog entry
Use the /chloggen skill to create a changelog entry:
- When making the draft PR, leave the description body empty.
- In the changelog entry, simply set
note to the CVE ID:
yq -i ".note = \"<CVE_ID>\"" "<chlog-filepath>"
Notes
- Previous CVE fixes:
git log --oneline | grep -i cve
- Replace directives can be removed in a future version bump once the upstream
component has updated its own dependency to >=
fixed_version.
- If
installed_version is a pseudo-version (contains a date like 0.20260409),
use the full pseudo-version string — Go resolves it correctly.