Safeguard
Supply Chain•

Malicious or just vulnerable: the first branch in a dependency runbook

How to tell a malicious dependency from a vulnerable one, and why the answer changes your first hour: containment, credentials and what reachability shows.

Safeguard Security Team
4 min read

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

QuestionVulnerableMalicious
Does exposure depend on reachability?Yes, oftenNo. Installation or import may be enough
Assume code executed?NoYes, wherever it was installed
Rotate credentials?Usually notYes, for every environment that installed it
Urgency driverExploitability and exposureTime since install
FixUpgrade or patchRemove, pin to a clean version, rebuild, clean machines
Typical ownerEngineering and securityIncident 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

  1. Read the source of the report. Does it say malware, backdoor, hijack, or a CVE-style flaw? Wording matters, but confirm it.
  2. 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.
  3. 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.
  4. 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.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.