CVE Fix Handler
Security audits surface CVEs but don't fix them. This skill picks up from there: find the vulnerable component, research the fix, upgrade or suppress it, and verify the build passes clean.
Step 1: Surface the CVE
Run the security audit for the project. If the CVE is already known from a failing build output, skip ahead to Step 2.
See Language Playbooks below for the exact command per ecosystem. Look for:
- CVE ID — e.g.,
CVE-2026-5588 - Vulnerable component — group/artifact or package name and version
- Severity — CVSS score and CWE classification
If multiple CVEs are found, address them one at a time starting with the highest severity.
Step 2: Trace the Version Source
Find where the vulnerable version is pinned in the project. The component may be a direct dependency or a transitive one pulled in by something else.
See Language Playbooks for the tracing command. Parse the output to identify:
- Which manifest file defines or pins the version (e.g.,
pom.xml,package.json,go.mod) - Which line / property to change
- Whether it's a property variable (e.g.,
${bouncycastle.version}) — in that case, update the property, not the individual dependency entry
Step 3: Research the CVE
Search online for the CVE to understand what you're fixing:
- Search for
CVE-<ID> <package-name> affected versions fix - Check the OSS Index entry:
https://ossindex.sonatype.org/vulnerability/CVE-<ID> - Check the NVD entry:
https://nvd.nist.gov/vuln/detail/CVE-<ID> - Check the package's GitHub releases or changelog for the patched version
Extract:
- Affected version range — confirm the current version is in range
- First patched version — the minimum version that resolves the CVE
- Latest stable version — prefer upgrading to latest unless there's a reason not to
Step 4: Find Available Upgrades
Check what versions are available for the package:
- Search Maven Central, npmjs.com, PyPI, pkg.go.dev, crates.io, or RubyGems depending on ecosystem
- Prefer the latest stable version unless it has known breaking changes
- If the latest version also has CVEs, find the lowest patched version that is clean
Step 5: Choose a Fix Strategy
Prefer upgrading. If a patched version exists, always upgrade — even if it's a major version bump. A suppression that masks a real vulnerability is not a fix.
Suppress only when:
- No patched version exists yet (CVE is newly disclosed)
- The vulnerable code path is not reachable in this application (document why)
- The dependency is test-only and the CVE is not relevant in that context
When suppressing, always add a comment with the CVE ID, the reason, and a date — so it can be revisited when a fix ships.
Step 6: Apply the Fix
Upgrading a version
Edit the version in the manifest file identified in Step 2. If the version is controlled by a property variable, update the property. If it's a transitive dependency with no direct pin, add an explicit version override (see Language Playbooks for how to do this per ecosystem).
Suppressing a CVE
Add the CVE to the project's exclusion/ignore list. See Language Playbooks for the exact mechanism per ecosystem. Include a comment with the CVE ID, a brief reason, and today's date.
Step 7: Verify
Re-run the security audit to confirm the CVE no longer appears. Then run the full build to make sure nothing broke.
See Language Playbooks for verify commands.
If the build fails after upgrading:
- Read the error carefully — it usually points to a changed API or renamed class.
- Check the package's migration guide or changelog for the version range.
- Fix compile errors, then re-verify.
Step 8: Report
Summarize:
- CVE ID, affected component, old version → new version
- CVSS severity and what the vulnerability was
- Whether it was fixed by upgrade or suppressed (and why, if suppressed)
- Build/audit status: clean or any remaining issues
Language Playbooks
Maven / Java
Surface CVEs:
mvn ossindex:audit
Trace version source:
# Replace <artifactId> with the vulnerable artifact
mvn help:effective-pom -Dverbose | grep <artifactId> -B2 -A2
The comment after each line shows which pom.xml and line number defines it.
Upgrade:
- If version is in a
<properties>block, update the property value. - If it's a transitive dependency with no explicit pin, add a
<dependencyManagement>entry in the rootpom.xmlto force the patched version.
Suppress (ossindex-maven-plugin):
Add to the plugin's <configuration> in pom.xml:
<excludeCoordinates>
<!-- CVE-XXXX-YYYY: no patched version available as of YYYY-MM-DD -->
<exclude>
<id>pkg:maven/org.example/artifact@1.2.3</id>
</exclude>
</excludeCoordinates>
Verify:
mvn clean compile
npm / Node.js
Surface CVEs:
npm audit
Trace version source:
# Find what pulls in the vulnerable package
npm ls <package-name>
This shows the full dependency tree path.
Upgrade:
- If it's a direct dependency, update the version in
package.jsonand runnpm install. - If it's transitive with a patched version available:
For cases wherenpm audit fixnpm audit fixcan't resolve it, add anoverridesentry topackage.json:
For Yarn, use"overrides": { "<package-name>": "<patched-version>" }resolutionsinstead ofoverrides.
Suppress: There is no standard npm-native suppression mechanism. Options:
- Use
.nsprcoraudit-resolve.json(if usingbetter-npm-audit) - Document the suppression decision in a comment in
package.json - Accept the advisory via
npm audit --audit-level=highto adjust the failing threshold
Verify:
npm audit
npm run build
npm test
Go
Surface CVEs:
govulncheck ./...
If govulncheck is not installed: go install golang.org/x/vuln/cmd/govulncheck@latest
Trace version source:
# Find what requires the vulnerable module
go mod why <module-path>
# Check current version
grep <module-path> go.mod
Upgrade:
go get <module-path>@<patched-version>
go mod tidy
If it's a transitive dependency, upgrade the direct parent that pulls it in, or add a direct require for the vulnerable module at the patched version.
Suppress:
Add to the govulncheck ignore list:
# In your CI/CD or Makefile:
govulncheck -ignore <CVE-ID> ./...
Or use a govulncheck.yaml config file if supported by your version.
Verify:
govulncheck ./...
go build ./...
go test ./...
Python
Surface CVEs:
pip-audit
# or:
safety check
Trace version source:
pip show <package-name>
grep -r <package-name> requirements*.txt pyproject.toml setup.cfg
Upgrade:
Update the version pin in requirements.txt or pyproject.toml, then:
pip install -r requirements.txt
# or:
pip install --upgrade <package-name>
Suppress:
# pip-audit ignore:
pip-audit --ignore-vuln CVE-XXXX-YYYY
# Or add to pyproject.toml:
# [tool.pip-audit]
# ignore-vulns = ["CVE-XXXX-YYYY"]
Verify:
pip-audit
python -m pytest
Rust / Cargo
Surface CVEs:
cargo audit
If not installed: cargo install cargo-audit
Trace version source:
# Show full dependency tree for the vulnerable crate
cargo tree -i <crate-name>
Upgrade:
# Upgrade a specific crate to a precise version
cargo update -p <crate-name> --precise <patched-version>
If the crate is a direct dependency, also update Cargo.toml.
Suppress:
Create or edit .cargo/audit.toml:
[advisories]
ignore = [
# CVE-XXXX-YYYY: no patched version available as of YYYY-MM-DD
"RUSTSEC-XXXX-XXXX",
]
Verify:
cargo audit
cargo build
cargo test
Ruby / Bundler
Surface CVEs:
bundle audit check --update
If not installed: gem install bundler-audit
Trace version source:
# Show what requires the vulnerable gem
bundle exec gem dependency <gem-name>
grep <gem-name> Gemfile Gemfile.lock
Upgrade:
Update the version constraint in Gemfile, then:
bundle update <gem-name>
Suppress:
bundle audit check --ignore CVE-XXXX-YYYY
Or add to .bundlerauditrc:
ignore:
- CVE-XXXX-YYYY
Verify:
bundle audit check --update
bundle exec rspec
Quick Reference
| Ecosystem | Surface | Trace | Verify |
|---|---|---|---|
| Maven | mvn ossindex:audit |
mvn help:effective-pom -Dverbose | grep <artifactId> -B2 -A2 |
mvn clean compile |
| npm | npm audit |
npm ls <pkg> |
npm audit |
| Go | govulncheck ./... |
go mod why <module> |
govulncheck ./... |
| Python | pip-audit |
pip show <pkg> |
pip-audit |
| Rust | cargo audit |
cargo tree -i <crate> |
cargo audit |
| Ruby | bundle audit |
bundle exec gem dependency <gem> |
bundle audit |