Skip to content

Instantly share code, notes, and snippets.

@alexgreenland
Last active March 31, 2026 17:53
Show Gist options
  • Select an option

  • Save alexgreenland/fdec0b0214022a803e87de47f7b5b819 to your computer and use it in GitHub Desktop.

Select an option

Save alexgreenland/fdec0b0214022a803e87de47f7b5b819 to your computer and use it in GitHub Desktop.
[Updated 31 Mar 2026] Digital Forensics & Incident Response (DFIR) for Axios NPM library compromise, Mar 2026

Digital Forensics & Incident Response (DFIR) for Axios library compromise, Mar 2026

Script to deep scan a batch of Node projects for known bad NPM packages, as listed in bad-deps.txt.

Fully checking each project found in your workspace (SEARCH_DIRS) or those declared in PROJECTS, we look for bad packages nested anywhere in the dependency tree, including node_modules and package-lock.json.

Authors Dan Cassey, Alex Greenland, Epi - epihq.com
License Public Domain (CC0)
Updated 31 Mar 2026

This script is intended as a first-pass check for developers and DFIR teams. It tells you if you depend on any version of the listed dependencies.

The bad-deps.txt file is intended to be thorough on a best-effort basis, but it is not an exhaustive list. The list represents the current state of threat intelligence in the industry.

Only specific versions of these dependencies are malicious, but the cyberattack indicates the known compromise of these libraries or their authors in March 2026.

We intentionally search for the packages without versions so you can see if you have any level of dependency on one of these libraries.

If a match is found, it does not necessarily indicate compromise. A match reveals potential compromise and requires further investigation, by comparing version numbers.

This script is provided as a public good, as-is, without warranties, on a best-effort basis, and is to be run at your own risk. You take full responsibility for the actions, discoveries, implications and remediation.

How to proceed

Run this script on developer machines and CI environments.

If the script finds matches

If matches are found, it does not indicate compromise by itself. It means you are using any version of the packages that have now been compromised. The script will tell you the specific version numbers you are using. To confirm compromise, compare them and check if you are using any of these versions:

  • axios@1.14.1
  • axios@0.30.4
  • plain-crypto-js@4.2.1
  • plain-crypto-js@4.2.0

plain-crypto-js is a key indicator of compromise (IOC).

If you see a version match, you need to remediate. Remove bad dependencies. Rotate secrets and credentials on machines, repositories, CI and cloud environments. Create new deployments.

If you don't see an exact version match for axios and there is no match for plain-crypto-js, you are reasonably safe in the context you run the script in.

If you are using a previous version of axios, and you don't pin your deps with package-lock.json, or you have a liberal version range specifier in package.json, do not run npm install or allow CI until you have pinned axios to a known-safe version.

axios is a legitimate package that has been compromised. There isn't a new version of axios published since. NPM has removed the malicious 1.14.1 version from the registry. The current known-safe version of axios is the official release on 27 March: 1.14.0. For now, you should define axios in your package.json without ranges, with the explicit version 1.14.0, and continue to monitor for malicious packages in your supply chain.

plain-crypto-js is a malicious and masquerading package for the legitimate library crypto-js. If any version of plain-crypto-js is found, it should be removed from node_modules and package-lock.json.

If the script doesn't find matches

If no matches are found, it indicates no versions of these libraries are depended upon, so you know with high certainty that there is no current compromise from these dependencies in your projects.


We check at a broader level for further assurance and safety. Going forward, in the case where you have a dependency on an old version of one of these libraries, you can decide whether to pin or remove the dependency.

Additional checks

If you use GitHub, you should also do a search in your org for "plain-crypto-js" and "axios". The template links below will search your org for these packages. Replace {YOUR_ORG_SLUG} with your org's URL slug - the org username that precedes your repo name.

Search your GitHub org for plain-crypto-js

https://github.com/search?q=org%3A{YOUR_ORG_SLUG}%20plain-crypto-js&type=code

Search your GitHub org for axios

https://github.com/search?q=org%3A{YOUR_ORG_SLUG}%20axios&type=code

Example

For example, if your org is "walmartlabs" (https://github.com/walmartlabs):

https://github.com/search?q=org%3Awalmartlabs%20plain-crypto-js&type=code

plain-crypto-js
axios
#!/bin/bash
#
############## Digital Forensics & Incident Response (DFIR) for Axios NPM library compromise, Mar 2026 ##############
#
# Script to deep scan a batch of Node projects for known bad NPM packages, as listed in bad-deps.txt.
#
# Fully checking each project found in your workspace (SEARCH_DIRS) or those declared in PROJECTS,
# we look for bad packages nested anywhere in the dependency tree,
# including node_modules and package-lock.json.
#
# Authors: Dan Cassey, Alex Greenland, Epi - epihq.com
# License: Public Domain (CC0)
# Updated: 31 Mar 2026
#
# This script is intended as a first-pass check for developers and DFIR teams.
# It tells you if you depend on any version of the listed dependencies.
#
# The bad-deps.txt file is intended to be thorough on a best-effort basis, but it is not an exhaustive list.
# The list represents the current state of threat intelligence in the industry.
#
# Only specific versions of these dependencies are malicious,
# but the cyberattack indicates the known compromise of these libraries or their authors in March 2026.
#
# We intentionally search for the packages without versions
# so you can see if you have any level of dependency on one of these libraries.
#
# If a match is found, it does not necessarily indicate compromise.
# A match reveals potential compromise and requires further investigation, by comparing version numbers.
#
# This script is provided as a public good, as-is, without warranties, and is to be run at your own risk.
# You take full responsibility for the actions, discoveries, implications and remediation.
#
#
############## HOW TO PROCEED ##############
#
# Run this script on developer machines and CI environments.
#
#
####### IT FOUND MATCHES:
#
# If matches are found, it does not indicate compromise by itself.
# It means you are using any version of the packages that have now been compromised.
# The script will tell you the specific version numbers you are using.
# To confirm compromise, compare them and check if you are using any of these versions:
#
# - axios@1.14.1
# - axios@0.30.4
# - plain-crypto-js@4.2.1
# - plain-crypto-js@4.2.0
#
# `plain-crypto-js` is a key indicator of compromise (IOC).
#
# If you see a version match, you need to remediate. Remove bad dependencies.
# Rotate secrets and credentials on machines, repositories, CI and cloud environments. Create new deployments.
#
# If you don't see an exact version match for `axios` and there is no match for `plain-crypto-js`,
# you are reasonably safe in the context you run the script in.
#
# If you are using a previous version of `axios`,
# and you don't pin your deps with package-lock.json, or you have a liberal version range specifier in package.json,
# do not run `npm install` or allow CI until you have pinned `axios` to a known-safe version.
#
# `axios` is a legitimate package that has been compromised.
# There isn't a new version of `axios` published since. NPM has removed the malicious 1.14.1 version from the registry.
# The current known-safe version of `axios` is the official release on 27 March: 1.14.0.
# For now, you should define `axios` in your package.json without ranges, with the explicit version 1.14.0,
# and continue to monitor for malicious packages in your supply chain.
#
# `plain-crypto-js` is a malicious and masquerading package for the legitimate library `crypto-js`.
# If any version of `plain-crypto-js` is found, it should be removed from node_modules and package-lock.json.
#
#
####### IT DIDN'T FIND MATCHES:
#
# If no matches are found, it indicates no versions of these libraries are depended upon,
# so you know with high certainty that there is no current compromise from these dependencies in your projects.
#
#
# We check at a broader level for further assurance and safety.
# Going forward, in the case where you have a dependency on an old version of one of these libraries,
# you can decide whether to pin or remove the dependency.
#
#
####### ADDITIONAL CHECKS:
#
# If you use GitHub, you should also do a search in your org for "plain-crypto-js" and "axios".
# The template links below will search your org for these packages.
# Replace {YOUR_ORG_SLUG} with your org's URL slug - the org username that precedes your repo name.
#
# https://github.com/search?q=org%3A{YOUR_ORG_SLUG}%20plain-crypto-js&type=code
# https://github.com/search?q=org%3A{YOUR_ORG_SLUG}%20axios&type=code
#
# For example, if your org is "walmartlabs" (https://github.com/walmartlabs):
# https://github.com/search?q=org%3Awalmartlabs%20plain-crypto-js&type=code
#
#
SEARCH_DIRS=("$HOME/workspace")
PROJECTS=(
# enter paths to roots of Node projects here, line separated
# OR leave blank to search all package.json-containing directories within SEARCH_DIRS
)
CWD=$(pwd)
BAD_DEPS=$(cat ./bad-deps.txt)
if [ ${#PROJECTS[@]} -eq 0 ]; then
for search_dir in ${SEARCH_DIRS[@]}; do
while IFS= read -r -d '' project; do
PROJECTS+=("$(dirname "$project")")
done < <(find "$search_dir" -path "*/node_modules" -prune -o -name "package.json" -type f -print0)
done
fi
for project in ${PROJECTS[@]}; do
cd $project
echo "Checking $project..."
FULL_LIST=$(npm list --all --silent)
for dep in ${BAD_DEPS[@]}; do
if [ $(echo $FULL_LIST | grep "$dep" | wc -l) != 0 ]; then
npm list $dep
fi
done
cd $CWD
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment