The NPM Supply Chain Attack

Sep 13, 2025

On September 8th, 2025, a supply chain attack compromised over 16 popular npm packages with over 2 billion downloads per week in total. The malware was designed to intercept cryptocurrency transactions in browser-only environment.

The day after, I was alerted by my direct manager to scan for security vulnerabilities in all projects I manage. Here is a summary of how I mitigated the risk.

Detection and Response

I found the quickest way to scan all of our files for any obfuscated code, thanks to this comment:

rg -u --max-columns=80 _0x112fa8
# Requires ripgrep: brew install rg

Luckily, none of our projects were affected. However, I still had to make sure that none of the compromised packages were installed as dependencies.

Here is the complete list of compromised packages:

ansi-regex@6.2.1
ansi-styles@6.2.2
backslash@0.2.1
chalk@5.6.1
chalk-template@1.1.1
color@5.0.1
color-convert@3.1.1
color-name@2.0.1
color-string@2.1.1
debug@4.4.2
error-ex@1.3.3
has-ansi@6.0.1
is-arrayish@0.3.3
proto-tinker-wc@1.8.7
supports-hyperlinks@4.1.1
simple-swizzle@0.2.3
slice-ansi@7.1.1
strip-ansi@7.1.1
supports-color@10.2.1
wrap-ansi@9.0.1

So I asked ChatGPT to help me write a command to check if any of these packages were installed as dependencies in our projects:

npm ls ansi-regex ansi-styles backslash chalk chalk-template color color-convert color-name color-string debug error-ex has-ansi is-arrayish proto-tinker-wc supports-hyperlinks simple-swizzle slice-ansi strip-ansi supports-color wrap-ansi

This will list out any of the compromised packages with their versions if they are installed.

Even this project has some of the compromised packages as dependencies, they are not directly used in my codebase:

nguyenhuutien.com
├─┬ next-mdx-remote@5.0.0
 └─┬ @mdx-js/mdx@3.1.1
   └─┬ remark-parse@11.0.0
     └─┬ mdast-util-from-markdown@2.0.2
       └─┬ micromark@4.0.2
         └── debug@4.4.1
└─┬ next@15.5.3 invalid: "latest" from the root project
  └─┬ sharp@0.34.3
    └─┬ color@4.2.3
      ├─┬ color-convert@2.0.1
       └── color-name@1.1.4
      └─┬ color-string@1.9.1
        ├── color-name@1.1.4 deduped
        └─┬ simple-swizzle@0.2.2
          └── is-arrayish@0.3.2

You can also find if any of these packages are installed in your project by searching for them in your lock files:

rg -n --glob '**/{package-lock.json,yarn.lock,pnpm-lock.yaml}' \
  -e 'ansi-regex\"?: \"6\.2\.1|ansi-styles\"?: \"6\.2\.2|backslash\"?: \"0\.2\.1|chalk\"?: \"5\.6\.1|chalk-template\"?: \"1\.1\.1|color\"?: \"5\.0\.1|color-convert\"?: \"3\.1\.1|color-name\"?: \"2\.0\.1|color-string\"?: \"2\.1\.1|debug\"?: \"4\.4\.2|error-ex\"?: \"1\.3\.3|has-ansi\"?: \"6\.0\.1|is-arrayish\"?: \"0\.3\.3|proto-tinker-wc\"?: \"1\.8\.7|supports-hyperlinks\"?: \"4\.1\.1|simple-swizzle\"?: \"0\.2\.3|slice-ansi\"?: \"7\.1\.1|strip-ansi\"?: \"7\.1\.1|supports-color\"?: \"10\.2\.1|wrap-ansi\"?: \"9\.0\.1'

Short-term Solutions: Package Version Pinning

Immediate protection involves pinning package versions in your package.json:

{
  "resolutions": {
    "ansi-regex": "6.2.0",
    "ansi-styles": "6.2.1",
    "backslash": "0.1.4",
    "chalk": "5.3.0",
    "chalk-template": "1.0.0",
    "color": "4.2.3",
    "color-convert": "2.0.1",
    "color-name": "1.1.4",
    "color-string": "1.9.1",
    "debug": "4.3.7",
    "error-ex": "1.3.2",
    "has-ansi": "5.0.1",
    "is-arrayish": "0.3.2",
    "proto-tinker-wc": "1.8.6",
    "supports-hyperlinks": "3.1.0",
    "simple-swizzle": "0.2.2",
    "slice-ansi": "6.0.0",
    "strip-ansi": "7.1.0",
    "supports-color": "9.4.0",
    "wrap-ansi": "8.1.0"
  }
}

Replace "resolutions" with "overrides" if you are using npm.

Clean installation process:

rm -rf yarn.lock node_modules
yarn install --check-files

Long-term Solutions: Regular Audits and Monitoring

Regularly audit your dependencies using tools like npm audit or Snyk. Set up monitoring for new vulnerabilities in your dependencies.

Resources

That's it. I hope this helps ;)


My Other Posts

No posts found.