How to Detect Known Malware in Your Supply Chain

Intermediate 20 minutes Security Engineers Security & Policy

Understand Chainsaw's malware index powered by OpenSSF data, review malware detections, and configure automatic blocking of malicious packages.

Overview

Chainsaw maintains an in-memory index of known-malicious packages sourced from the OpenSSF Malicious Packages database. Every package request is checked against this index in O(1) time — if a match is found, the package’s trust score is instantly set to -100 and the request can be blocked before the malicious code ever reaches a developer’s machine.

Prerequisites

  • Chainsaw deployed and receiving traffic (malware detection is automatic)
  • Manager role or above to configure policies

Step 1: Understand the Malware Index

Chainsaw’s malware detection uses the OSV (Open Source Vulnerabilities) format from the OpenSSF database:

ComponentDescription
SourceOpenSSF Malicious Packages database
FormatOSV JSON entries
LookupO(1) hash-based, per ecosystem + package name + version
DataMalware ID (e.g., MAL-2024-0001), summary, affected version ranges
UpdateRefreshed automatically in-process, includes introduced/fixed version range support
Malware index architecture
The in-memory malware index provides instant lookups on every package request

What Gets Detected

The index covers known malicious packages across ecosystems:

  • npm — Typosquats, crypto miners, credential stealers
  • PyPI — Backdoored packages, data exfiltrators
  • Cargo — Supply chain attack packages
  • Swift — Bridged from GHSA (ecosystem=swift&type=malware); gated behind cfg.EnableGHSAMalware
  • Docker — Digest-first lookup (sha256:…) and name+tag fallback via a Docker-specific feed. An embedded seed plus an optional remote feed (DockerMalwareFeedURL) are loaded at startup; gated behind cfg.EnableDockerMalware (default on)
  • Other ecosystems — As reported to OpenSSF
The Docker feed closes a long-standing gap: the OpenSSF malicious-packages database publishes almost no Docker entries, so image-based malware was invisible to the standard index. Chainsaw ships a curated seed of known-malicious digests in the binary and can additionally pull a self-hosted remote feed — so digests that roll up on your internal CTI feed propagate to every chainsaw replica without a redeploy.
Malware detection is a synchronous check — it runs inline on every request with near-zero latency. There’s no configuration needed; it’s always active.

Step 2: Review Malware Detections

In the Bill of Materials

Navigate to Bill of Materials and look for packages with a Malware Status of malicious.

BOM showing malware status column
Packages flagged as malicious appear with their malware ID in the BOM

Click on a malicious package to see:

FieldDescription
Malware Statusmalicious
Malware IDOSV identifier (e.g., MAL-2024-0001)
Trust Score-100 (instant kill — overrides all other signals)
SummaryDescription of the malware behavior
Malware detection details for a package
Full details of a malware detection including the OSV identifier

In the Dashboard

Malware blocks appear as critical severity violations on the overview dashboard.

Critical violations from malware detection
Malware blocks surface as critical violations on the dashboard

Step 3: Create a Malware Blocking Policy

While malware detection runs automatically, you need a policy to enforce blocking. Without a policy, detections are recorded but packages may still be served.

Navigate to Policies and create:

  1. Name: Block Known Malware
  2. Action: Block
  3. Condition: Malware Status → malicious
  4. Scope: All repositories
  5. Precedence: Very high (this should be near the top of your policy stack)
Creating a malware blocking policy
Create a policy that blocks all known-malicious packages
Place the malware blocking policy above all exception/allow policies. No exception should override a confirmed malware detection.

Step 4: Understand Trust Score Impact

Malware detection has a special “kill switch” effect on the trust score:

Normal Score ComponentsPoints
Vulnerability check0-20
Provenance0-25
License0-10
Package age0-10
Typosquat check-30 to +10
Source repo0-10
Version count0-10
Checksum0-5
Total range-30 to 100
Malware detected-100
Overrides all other componentsInstant minimum score

A trust score of -100 makes it immediately obvious in any view that the package is dangerous.

Step 5: Respond to a Malware Detection

When malware is detected in your supply chain:

Immediate Actions

  1. Confirm the block — Verify the package was blocked in the Traffic or Violations view
  2. Identify affected clients — Filter audit logs by the malicious package name
  3. Check if it was ever installed — Look at the BOM for last_outcome = success (pre-policy)
  4. Notify affected teams — Share the malware ID and affected versions

Investigation

Billy: "Show me all events for package [malicious-package] in the last 90 days"
Billy: "Which clients installed [malicious-package] before it was blocked?"
Investigating a malware detection with Billy
Use Billy to trace the impact of a malware detection across your organization

Remediation

If the malicious package was installed before detection:

  1. Identify all systems that received the package
  2. Remove the package from node_modules / site-packages / local cache
  3. Rotate any credentials that may have been exposed
  4. Audit system logs for suspicious activity
  5. Update lockfiles to exclude the malicious version

Step 6: Monitor the Malware Index

Chainsaw refreshes the malware index automatically from the OpenSSF database using the in-app data_sources.openssf scheduler. To ensure you have the latest detections:

  • Keep data_sources.openssf.enabled turned on
  • Use the default 6-hour refresh interval unless you have a stricter operational requirement
  • Monitor Chainsaw logs or the Settings page for last success time, next run, and the active OpenSSF revision
  • Use the manual refresh action when you want to force an immediate sync after a high-priority advisory lands
The OpenSSF database is continuously updated by the security community. Chainsaw’s default 6-hour refresh interval keeps malware signatures current without requiring service restarts.

Step 7: Version Range Handling

The malware index supports version ranges, not just exact versions. An OSV entry might specify:

{
  "affected": [{
    "package": { "name": "malicious-lib", "ecosystem": "npm" },
    "ranges": [{
      "type": "SEMVER",
      "events": [
        { "introduced": "1.0.0" },
        { "fixed": "1.0.5" }
      ]
    }]
  }]
}

This means versions 1.0.0 through 1.0.4 are malicious, but 1.0.5 (the fixed version) is clean. Chainsaw handles this automatically during index lookup.

Next Steps