# Fix Cve

> 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.

- Skill: `newrelic/fix-cve` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add newrelic/fix-cve`
- Raw SKILL.md: https://api.skillmd.com/api/skills/newrelic/fix-cve/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: newrelic (https://skillmd.com/u/newrelic)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/newrelic/fix-cve

---


# 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:

```bash
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:

```bash
make generate-sources
```

Then grep the go.sum files for the affected module:

```bash
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:

```bash
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**

```bash
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:

```bash
# e.g. for receiver/prometheusreceiver:
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:`:

```yaml
  # Why: Fixes <CVE_ID>; can be removed when <upstream component> pulls in >= <fixed_version>
  - <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:
```yaml
replaces:
  # Why: Fixes CVE-2026-42154; can be removed when prometheusreceiver pulls in >= v0.311.3
  - 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:

```bash
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.

