Dependency patching
Dependency patching is the routine work of keeping the open-source and third-party components you ship free of known vulnerabilities: confirming that each advisory applies to what you actually ship, upgrading to a fixed version, and recording the reason when you do not.
Every advisory for a component you ship tells attackers where to look, and most findings arrive through packages you never chose directly: in a measured Node.js example on this site, 11 of 16 came from express 4.19.2 and the packages it pulls in. Without a routine, teams chase every alert or ignore them all; with one, a single parent upgrade often closes many findings at once.
- Who
- The team that owns the service, with update bots doing routine bumps and AppSec settling disputed or exploited cases
- When
- When a scanner or update bot reports a new advisory, and before each release
- How often
- Update pull requests reviewed weekly; due dates from the prioritization policy; exploited cases at once
- You end up with
- Upgraded lockfiles and rebuilt artifacts, and a record per finding: fixed, not affected with evidence, or accepted with an expiry
Do this
Scan what you ship and automate updates
Scan lockfiles on every pull request, and built images on a schedule, with a tool such as OSV-Scanner, Dependabot or another software composition analysis tool. Turn on automated security updates: Dependabot, for example, opens a pull request to the minimum version that includes the patch. Look up a single package with OSV dependency lookup.
Collapse duplicates and confirm the copy ships
One vulnerability can arrive as GHSA, PYSEC and CVE records; keep one finding per alias group, package, version and artifact. Confirm the copy reaches the shipped artifact with
npm ls <package> --omit=devor the image SBOM. Match ecosystem and package name exactly, and for operating system packages use the distribution's advisory, because a backported fix keeps the old version number.Check the advisory's precondition
Most advisories say what must be true for the bug to matter, such as a route shape, attacker-controlled templates or user input in a cookie name. Check it with something you can rerun: a code search, a test, or a call-graph tool such as govulncheck, which separates Go vulnerabilities your code calls from those it only imports. Record the scope of the check and what would reopen it.
Upgrade the parent first, then rescan
Most transitive findings close when their parent moves, so upgrade direct dependencies before analyzing each child; the OWASP Vulnerable Dependency Management Cheat Sheet also advises acting on the direct dependency. Rescan the new lockfile before merging, because an upgrade can add findings. If the parent's range cannot reach the fix, use an
overridesorresolutionsentry with tests, or record a dated exception.Test, rebuild and verify what runs
Run the test suite against the upgraded dependency, then rebuild without a cached dependency layer and deploy. Close the finding only when a rescan of the built image or its SBOM shows the fixed version and every environment, including workers and scheduled jobs, runs that digest. A merged pull request is an intermediate step, not the fix.
Record one outcome per finding
Give each finding exactly one outcome and an owner: fixed by its due date (Risk-based prioritization), not affected with a VEX
not_affectedstatement and its justification, accepted with an expiry and a compensating control, or escalated. Keep the original detection beside the decision, so a later scan of the same package can be matched to it.Handle no-fix and exploited cases on purpose
With no fixed version yet, apply the maintainer's workaround or isolate the affected feature, and track it with an expiry. Make a plan for each unmaintained package, such as replacing it, as SSDF task PW.4.4 suggests. If the finding is in CISA's KEV catalog or credibly exploited and you run it, stop triaging and respond as an incident (Respond to an exploited or malicious dependency).
Done when
Each dependency finding has a recorded decision with evidence, and known-exploited ones are fixed first.
Mark it in the gap checkCommon mistakes
- Closing on a merged pull request. A cached build layer or a rarely deployed worker can keep shipping the old version, so close on the deployed digest.
- Treating development-only copies as production findings, or production copies as development-only without checking. Both waste time or hide real exposure.
- Pinning the first fixed release and moving on. Eight days after the React2Shell fix, React disclosed three more vulnerabilities in the same code, so recheck the advisory until the case closes.
- Recording "not reachable" without its scope. A negative result covers only the code and entry points examined, and it expires when either changes.
- Suppressing a scanner rule or a whole package to quiet the noise. Suppress one vulnerability ID for one package, with a reason and an expiry.
Which outcome does a finding get?
Route each finding to exactly one row. The due date for a fix comes from your prioritization policy, not from this table.
| Outcome | Use it when | Record |
|---|---|---|
| Incident | Exploited (KEV or credible reports) and present in a deployed artifact | An incident ticket with the affected digests |
| Fix by due date | Shipped, and the precondition holds or cannot be ruled out | Due date, owner and the planned upgrade |
| Fix on the normal cadence | Shipped, precondition absent, fix available | VEX not_affected with a justification and a reopen trigger |
| Not affected | Not in any shipped artifact, such as a development-only copy | Scope evidence, such as npm ls --omit=dev output |
| Not a match | Wrong ecosystem or package, or a distribution backport already fixed it | The mismatch and any distribution advisory |
| Accepted risk | Shipped, with no fix or no compatible fix yet | Owner, expiry date and compensating control |
Tools and guides
- Tool: OSV dependency lookup
- Tool: SBOM checker
- Workflow: Respond to a vulnerability
- Triage new dependency vulnerability findings
Turn a weekly batch of Dependabot, OSV-Scanner or npm audit findings into a short list of distinct, shipped, reachable issues, each routed to one outcome: fix, not affected, accept or escalate.
- Respond to an exploited or malicious dependency
When a dependency vulnerability is being exploited, or a package version is malicious, triage gives way to incident response: find every running copy, contain it, patch and redeploy, hunt for exploitation, rotate secrets and close on deployed evidence.
- Use VEX without losing vulnerability evidence
Produce and consume precise vulnerability status statements tied to the product, version, justification and evidence.
Standards
- NIST SSDF 1.1
- PW.4 Reuse Existing, Well-Secured Software When Feasible Instead of Duplicating FunctionalityRV.2 Assess, Prioritize, and Remediate Vulnerabilities
- OWASP SAMM 2
- Secure BuildEnvironment Management
Sources
- OWASP Vulnerable Dependency Management Cheat Sheet
- OSV-Scanner: usage
- GitHub Docs: About Dependabot security updates
- Go: Tutorial: Find and fix vulnerable dependencies with govulncheck
- npm Docs: npm ls. npm v11.
- OpenVEX specification. v0.2.0.
- React: Denial of Service and Source Code Exposure in React Server Components. 11 December 2025, updated 26 January 2026.
- NIST SP 800-218: Secure Software Development Framework (SSDF) Version 1.1 (PW.4.4, RV.2). February 2022.
- OWASP SAMM: Secure Build, Software Dependencies stream
- OWASP SAMM: Environment Management, Patching and Updating stream