An npm worm tabletop tests whether your team can answer three questions fast: did we install the bad versions, what credentials did they reach, and are we now publishing anything we should not be? This script covers all three in one hour with four injects.
The real event behind the script
In September 2025, CISA issued an alert about a widespread npm compromise by a self replicating worm called Shai-Hulud. CISA reported over 500 packages affected. The malware harvested credentials, including GitHub personal access tokens and cloud API keys for AWS, Google Cloud and Azure, sent them to an attacker controlled endpoint and used stolen npm access to push malicious code into further packages.
CISA's recommended actions give the exercise its backbone: review lockfiles including nested dependencies, check artifact caches, pin to versions published before 16 September 2025, rotate developer credentials, require phishing resistant MFA, block outbound connections to webhook.site domains, and review GitHub apps, webhooks and secrets.
Run the exercise with a fictional package family so the focus stays on your process.
Setup
- Facilitator, scribe, one frontend or Node engineer, one platform engineer, one security lead.
- A rule: every answer names a tool, a command or a person.
- Hand out a one page contact sheet with registry owners and cloud admins.
Injects
Inject 1, minute 5. A security feed lists dozens of npm packages, including a utility three levels deep in your frontend. Ask: how do you search every lockfile, including transitive dependencies? How do you search build caches and internal registry mirrors? Who owns that search?
Inject 2, minute 18. You find the bad version in two services, installed on developer laptops and in CI last Tuesday. Ask: what could a postinstall script read on a laptop? On a CI runner? List the credential types and where each lives.
Inject 3, minute 32. A colleague notices a new public repository under a developer's GitHub account that they did not create. Ask: is this a sign of compromise, who disables the account, and how do you handle a developer who is travelling?
Inject 4, minute 45. Your own internal package, published with a shared npm token, shows a version nobody released. Ask: how do you stop further publishes, and how do you tell customers?
Discussion questions
- Do your lockfiles pin exact versions, and does CI install from them without updating?
- Which tokens are long lived? Which are scoped to one package?
- If you revoke an npm token, how long until it takes effect? npm's documentation notes a delay of up to an hour.
- Who can publish your packages today, and is that list reviewed?
Scoring the exercise
| Area | Good sign | Gap sign |
|---|---|---|
| Inventory | Lockfile search finished in under 30 minutes | Nobody knows where lockfiles are |
| Credentials | Token list per developer and per pipeline | "Probably the usual ones" |
| Containment | Named owner can disable accounts out of hours | Waiting for one admin |
| Communication | Draft statement with approver | Debate about who speaks |
Debrief
End by picking the three cheapest fixes, such as exact version pinning, shorter token lifetimes and a registry publish allow list, and assign owners. Record outcomes in an after-action report. For the revoke steps you will rehearse, see the timed secret rotation drill.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how a dependency inventory includes nested packages, which is exactly what inject 1 asks you to find.
Safeguard provides SBOM and dependency scanning and a free scan at gold.safeguard.sh/scan if you want a starting inventory.
Quick check
Do we need a real malicious package to run this?
No. Use a fictional package name and paper injects. Never install real malware as part of an exercise.
Who should attend?
At least one person who owns CI, one who owns package publishing, and one who can approve credential revocation. Add a communications lead for inject 4.
Sources
- CISA alert on the widespread npm supply chain compromise
- npm documentation on revoking access tokens
Last reviewed: 19 October 2026.