Join our Newsletter — 33% off our NHI Course
Home› Guides› Malicious Open Source Package Response Playbook: Scoping, Containing…
Template Incident Response & Forensics

Malicious Open Source Package Response Playbook: Scoping, Containing and Rotating After npm or PyPI Malware

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 27 October 2026 12 min read
On this page

A malicious npm or PyPI package runs with the full rights of whoever installed it, which usually means a developer laptop full of tokens or a CI runner full of secrets. These incidents move faster than a normal supplier compromise: an install script fires on npm install or pip install, credentials leave within seconds, and in worm campaigns the stolen publishing tokens are used to infect further packages within hours. This template is a playbook for one specific scenario: a dependency you installed (directly or transitively) has been reported as malicious. It covers dependency scoping across lockfiles, caches and images, host triage, credential rotation and registry actions. It is written for security operations, application security and platform teams. Adapt roles, tools and timings to [Organisation].

How to use this template

  • Replace text in square brackets, such as [Organisation], [Incident manager] and [AppSec lead], with your names and contact routes, then approve the playbook through your normal policy process.
  • Steps are numbered and owned. Steps marked Decision: need a recorded decision, the decision maker and the time.
  • Examples use npm and PyPI terms. Map them to other ecosystems you use (RubyGems, crates.io, NuGet, Maven, Go modules); the steps are the same.
  • This playbook is the package-specific branch of the Supply Chain Compromise Response Playbook. If the malicious code reached your build system or release path, run the CI/CD Pipeline Compromise Playbook in parallel. If you are the maintainer whose package was hijacked, sections 4 to 7 also apply to your publishing account.
  • It follows the incident response life cycle in NIST SP 800-61 Rev. 3, which is organised around the CSF 2.0 Respond and Recover functions.

1. Scope and triggers

In scope: open source packages pulled from public registries into developer workstations, CI/CD runners, container images, serverless bundles and production hosts, including transitive dependencies, internal registry mirrors and proxy caches. Out of scope: vulnerabilities without malicious intent (use your vulnerability management process).

TriggerTypical sourceATT&CK
Package version reported as malwareOpenSSF Malicious Packages (OSV reports), GitHub malware advisories, registry takedown notice, vendor research blogT1195.001 Compromise Software Dependencies and Development Tools
Government or CERT alert naming a campaignCISA, NCSC or national CERT alertT1195.001
Install-time script behaviour on a hostEDR alert: node or python spawning shells, downloading runtimes or reading credential files during installT1059.007 JavaScript, T1546.016 Installer Packages
Credential harvesting signalReads of ~/.npmrc, ~/.aws/credentials, .env files, cloud metadata requests from build jobsT1552.001 Credentials In Files, T1552.005 Cloud Instance Metadata API
Exfiltration or token misuseUnexpected public repositories, webhook endpoints, publishes you did not make, secret scanning alertsT1567 Exfiltration Over Web Service, T1528 Steal Application Access Token

Severity: Critical if the package ran on a CI runner with deployment or publishing secrets, or on an administrator workstation; High if it ran on any developer machine; Medium if it is present in a lockfile or image but evidence shows it never executed; Low if only a non-executed cached copy exists.

2. Roles and contacts

RoleResponsibilitiesContact
[Incident manager]Declares the incident, sets severity, owns decisions and the timeline[Name, out-of-hours route]
[AppSec lead]Scopes affected repositories, lockfiles, images and mirrors; confirms malicious versions[Team queue]
[SOC and DFIR]Host triage, EDR hunting, network and identity log review[SOC queue]
[Platform engineering]Blocks versions in the registry proxy, pauses pipelines, rebuilds runners and images[On-call rota]
[Secret owners and NHI team]Revoke and rotate every credential reachable from affected hostsFrom the secrets inventory
[Package maintainers]If one of your own packages was republished: deprecate, unpublish or yank, and publish a clean version[Owners of record]
[Legal, privacy and communications]Customer, regulator and open source community notices[Contacts]

3. Detection and triage

  1. Open the incident and record the package name, ecosystem, malicious versions, first publish time and the advisory or report identifier. Treat the earliest malicious publish time as the start of your hunt window.
  2. Find every reference. Search lockfiles across all repositories (package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, uv.lock, pinned requirements.txt), including nested dependencies, as CISA advised for the Shai-Hulud campaign. Then search your registry proxy or artefact repository for cached copies, container image SBOMs and serverless bundles.
  3. Find every execution. A package in a lockfile is exposure; an install is execution. Use CI job logs for installs in the window, EDR process trees on developer machines (package manager spawning curl, sh, a new runtime binary or a credential-reading process) and proxy logs for registry downloads by host.
  4. List reachable credentials per host. For each machine or runner that executed the package, list what it could read: npm and PyPI tokens, GitHub and GitLab tokens, SSH keys, cloud CLI credentials, CI secrets injected into the job, .env files, browser sessions and password manager CLIs. This list drives section 5.
  5. Check for spread. Look for package versions published by your accounts in the window, new repositories, new workflow files, new self-hosted runner registrations and new deploy keys. The Shai-Hulud npm worm used each stolen npm token to republish the victim's own packages and registered infected hosts as self-hosted runners for persistence.
  6. Preserve evidence before cleaning: the malicious tarball or wheel (from your proxy cache), CI job logs (they may expire), EDR telemetry, and a disk image of at least one affected workstation.
  7. Decision: confirm severity and whether to run the CI/CD playbook in parallel. Record who decided and when.
Evidence sourceQuestion it answersRetention risk
Lockfiles and SBOMsWhich projects and images contain the versionLow: in source control
Registry proxy logsWhich hosts downloaded it, and whenMedium: check log retention
CI job logsWhich jobs installed it, with which secrets in scopeHigh: often 30 to 90 days, and may be public
EDR process and file telemetryWhether install scripts ran and what they readMedium
Registry, GitHub and cloud audit logsWhether stolen tokens were usedMedium: export early

4. Containment

  1. Block the versions in your registry proxy or artefact repository so no new install can fetch them, and purge cached copies after preserving one for evidence.
  2. Pause affected pipelines and any scheduled jobs that resolve dependencies without a lockfile.
  3. Disable install scripts on CI while the incident is live: set ignore-scripts=true in the CI .npmrc. For npm 11, min-release-age (a number of days) or before (a date) limit installs to versions published before a cut-off, which stops freshly hijacked releases resolving.
  4. Isolate executing hosts. Network-isolate developer machines through EDR; take ephemeral runners out of the pool; deregister self-hosted runners.
  5. Block known exfiltration endpoints named in the advisory at the proxy and firewall (CISA advised blocking webhook.site for Shai-Hulud) and review prior connections to them.
  6. Revoke the highest-risk credentials first: publishing tokens and source control tokens, because these enable spread. Revoke before you rotate; deleting a file does not invalidate a token.
  7. Decision: whether to freeze all dependency updates organisation-wide until scoping is complete.

5. Eradication

  1. Rebuild, do not clean. Reimage developer machines that executed the package and destroy affected runners and build caches. Install scripts can drop persistence outside the project directory.
  2. Rotate every credential on the section 3 list, owner by owner, using the Secrets Rotation Runbook Template. Order: package registry tokens, source control tokens and SSH keys, CI secrets, cloud keys, SaaS API keys, then everything else on the host.
  3. Remove attacker persistence found in section 3: rogue repositories, workflow files, runners, deploy keys, OAuth and GitHub App grants, webhooks and cloud identities created with stolen keys. CISA's guidance included removing unnecessary GitHub Apps and OAuth applications and auditing repository webhooks and secrets.
  4. Pin to a known good version in every affected project, regenerate lockfiles, and rebuild images from clean bases.
  5. If you maintain an affected package: on npm you can unpublish within 72 hours if nothing depends on it, otherwise use npm deprecate and publish a clean higher version (a name@version can never be reused). On PyPI, yanking hides a release from normal resolution (except exact == pins), and PyPI administrators can quarantine a project so pip cannot install it. Report the malware through the registry's own process.
Credential found on hostRevoke actionReplacement
npm tokenRevoke in npm account settings; check for publishes made with itTrusted publishing (OIDC); granular tokens only where needed. See the npm Tokens Security Guide
PyPI API tokenRemove in account settings; check release historyPyPI trusted publishing from CI
GitHub PAT or OAuth tokenRevoke; review security log for new keys and appsFine-grained, short-lived tokens. See the GitHub Personal Access Tokens Security Guide
Cloud access keysDeactivate; review CloudTrail or activity logs from the hunt startWorkload identity federation or SSO-issued short sessions
CI secretsRotate at source; delete unused secretsOIDC to cloud; secrets scoped to the steps that need them

6. Recovery

  1. Re-enable pipelines one at a time, with install scripts off by default and an allow-list for packages that genuinely need them.
  2. Return rebuilt workstations to users with fresh credentials and confirmed phishing-resistant MFA on registry and source control accounts.
  3. Monitor for use of any revoked credential (failed authentications show what you missed) and for new publishes from your organisation's accounts for at least 30 days.
  4. Decision: criteria to close: all executing hosts rebuilt, all listed credentials rotated, no attacker persistence found, dependency freeze lifted.

7. Communication and notification

AudienceOwnerWhenContent
Developers[AppSec lead]Within the first hourStop installs, do not run the package, report if installed, expect credential resets
Executives[Incident manager]At declaration and dailyScope, credentials at risk, customer impact
Downstream users of your packages[Package maintainers]As soon as a clean version existsAffected versions, safe version, indicators, rotation advice
Registries and community[AppSec lead]On confirmationMalware report with file hashes; OSV-format report where you have one
Customers and regulators[Legal and privacy]Per contract and lawIf stolen credentials reached personal or customer data

8. Post-incident review

  • Hold the review within [10] working days and build a timeline: malicious publish, first install in [Organisation], detection, revocation, last rotation.
  • Ask: how long did it take to find every lockfile and image containing the version? Did CI logs still exist? Which credentials had no owner?
  • Track what made the blast radius large: long-lived tokens on laptops, secrets in the environment of dependency install steps, install scripts enabled by default.
  • Feed changes into dependency policy, CI hardening and this playbook. Record the version change below.

Implementation guidance

Prepare before the incident. The steps above are only fast if the groundwork exists:

  • Single route to registries: force all installs through a registry proxy so blocking and download logs exist.
  • Searchable lockfiles and SBOMs for every repository and image, so scoping takes minutes, not days.
  • Malware feeds: subscribe to the OpenSSF Malicious Packages dataset (OSV format) and your platform's malware advisories, and match them automatically against lockfiles.
  • Install hygiene: npm ci with committed lockfiles, ignore-scripts on CI, a release-age cool-off for new versions, and pip hash-checking mode for Python builds.
  • Publishing identities: move your own packages to trusted publishing and set npm publishing access to require two-factor authentication and disallow tokens. npm revoked all classic tokens on 9 December 2025 and caps granular write tokens at 90 days, so legacy automation may already be broken or due to expire.
  • Secret-free installs: fetch secrets only in the steps that use them, never in the job environment during dependency installation.

Small vs large organisations. A small team can run this with one incident manager and the developers themselves, provided there is a list of who holds which tokens; prioritise trusted publishing and a release-age cool-off. A large organisation needs automated lockfile search across thousands of repositories, a registry proxy with block lists, and pre-agreed rotation owners; its bottleneck is usually credential ownership, not detection.

FrameworkMapping
NIST CSF 2.0DE.CM-09, DE.AE-02, RS.MA-01, RS.AN-03, RS.MI-01, RS.MI-02, RC.RP-01, GV.SC-07
NIST SP 800-53 Rev. 5IR-4 Incident Handling, IR-6 Incident Reporting, SR-3 Supply Chain Controls and Processes, SR-4 Provenance, SR-11 Component Authenticity, SI-7 Software, Firmware, and Information Integrity, CM-7 Least Functionality
MITRE ATT&CKT1195.001, T1059.007, T1546.016, T1552.001, T1552.005, T1528, T1567

Readiness metrics: time from advisory to complete list of affected repositories and images; time from detection to revocation of publishing tokens; percentage of CI jobs with install scripts disabled; percentage of your packages on trusted publishing; percentage of reachable credentials rotated within 24 hours.

Common failure patterns:

  • Scoping direct dependencies only, missing the transitive copy that actually ran.
  • Rotating the npm token but not the cloud keys and SSH keys on the same laptop.
  • Cleaning a workstation instead of rebuilding it.
  • Waiting too long: in the Shai-Hulud second wave, Wiz found more than 60% of leaked npm tokens still valid a week later.
  • Losing CI logs to retention before the hunt reaches them.

References: NIST: SP 800-61 Rev. 3 Incident Response Recommendations · CISA: Widespread Supply Chain Compromise Impacting npm Ecosystem · OpenSSF: Malicious Packages · npm Docs: Trusted publishing · npm Docs: Unpublish policy · PyPI Docs: Yanking · PyPI Blog: Project quarantine

Version history: v1.0 [date], approved by [Approver]. Review every [12] months or after each incident.

Related NHI Mgmt Group resources: Supply Chain Compromise Response Playbook · CI/CD Pipeline Compromise Playbook · npm Tokens Security Guide · Leaked Credential Response Playbook

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 27 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org