A vulnerable dependency has a flaw an attacker might exploit. A malicious dependency is code written to harm you, and it may already have run. The first branch in your runbook should ask which one you face, because malicious means assume execution and exposed secrets, while vulnerable means check exposure and patch.
Definitions
Vulnerable. A legitimate package contains a defect. The code does what its authors intended apart from the flaw. Risk depends on whether your code reaches the flaw and whether an attacker can supply the input.
Malicious. The package, or a specific version, contains code intended to steal, destroy or gain access. It may come from a hijacked account, a typosquat, or a poisoned release. The harmful code can run at install time or at import time, so installation alone can be enough.
Compromised legitimate package. A subtype of malicious: the name is trusted, but a particular version was tampered with. Treat it as malicious for the affected versions.
How the first hour differs
| Question | Vulnerable | Malicious |
|---|---|---|
| Does exposure depend on reachability? | Yes, often | No. Installation or import may be enough |
| Assume code executed? | No | Yes, wherever it was installed |
| Rotate credentials? | Usually not | Yes, for every environment that installed it |
| Urgency driver | Exploitability and exposure | Time since install |
| Fix | Upgrade or patch | Remove, pin to a clean version, rebuild, clean machines |
| Typical owner | Engineering and security | Incident commander |
Reachability analysis helps a great deal on the left side and much less on the right. For a vulnerable function nobody calls, it can lower urgency. For a malicious install script, whether your code calls the package is beside the point. See does reachability analysis help with a malicious package incident.
A simple decision flow
- Read the source of the report. Does it say malware, backdoor, hijack, or a CVE-style flaw? Wording matters, but confirm it.
- Check the advisory type. Many databases separate malware advisories from vulnerability advisories. GitHub states that its malware advisories are published from the npm security team and the OpenSSF Malicious Packages repository.
- When unsure, treat it as malicious until you can show otherwise. The cost of a few hours of extra caution is lower than the cost of missing a secret theft.
- Record the call and who made it, with the evidence at that moment.
What changes after you decide
Choose malicious and you open an incident, preserve logs and caches, block the version, list every environment that installed it, and start credential rotation in order of blast radius. Choose vulnerable and you open a ticket with a severity, run exposure checks, and follow your patch policy.
The call can change. A report may start as "vulnerable" and be revised to "malicious" when new evidence arrives. Build the runbook so switching branches is easy and explicit.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how exposure is judged for a vulnerable package, then ask why that logic does not carry over to a malicious one.
Quick check
Can a vulnerable package also be malicious?
They are separate questions. A package can have both a flaw and a tampered release. Check each.
What should we assume if the report is unclear?
Assume malicious until you can show otherwise, and downgrade when evidence supports it.
Safeguard can help with the inventory side of this work. SBOM and dependency scanning show where a package and version appear across your projects, and policies and gates can stop a flagged version at the pull request. You can try a free scan at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.