Live
Black Hat USADark ReadingBlack Hat AsiaAI BusinessAI & Tech brief: Ireland ascendant - The Washington PostGNews AI EULenovo Legion Go 2 suddenly costs $650 more as RAMageddon lays waste to gaming hardwareThe VergeVultr says its Nvidia-powered AI infrastructure costs 50% to 90% less than hyperscalersThe New StackDeepseek v4 will reportedly run entirely on Huawei chips in a major win for China s AI independence pushThe DecoderHow to Make AI Work When You Don’t Have Big Tech MoneyTowards AIToshiba starts shipping SMR MAMR enterprise hard drives offering up to 34TB of storageTechSpotMIT created duplicate AI workers to tackle thousands of different tasks. The verdict? Most of the time AI is still just minimally sufficientFortune TechAlgorithms of Falsehood: The Challenges of Governing AI-Generated Disinformation - orfonline.orgGoogle News: Generative AIThe Cathedral, the Bazaar, and the Winchester Mystery HouseO'Reilly RadareM Client Adds Generative AI Features - Let's Data ScienceGoogle News: Generative AItrunk/364516d4725fd98c0f2fd2301366409bc54cbc5b: [dtensor][pointwise_ops] removing dead code (#178975)PyTorch ReleasesThe fight on the right over AI - politico.euGNews AI USABlack Hat USADark ReadingBlack Hat AsiaAI BusinessAI & Tech brief: Ireland ascendant - The Washington PostGNews AI EULenovo Legion Go 2 suddenly costs $650 more as RAMageddon lays waste to gaming hardwareThe VergeVultr says its Nvidia-powered AI infrastructure costs 50% to 90% less than hyperscalersThe New StackDeepseek v4 will reportedly run entirely on Huawei chips in a major win for China s AI independence pushThe DecoderHow to Make AI Work When You Don’t Have Big Tech MoneyTowards AIToshiba starts shipping SMR MAMR enterprise hard drives offering up to 34TB of storageTechSpotMIT created duplicate AI workers to tackle thousands of different tasks. The verdict? Most of the time AI is still just minimally sufficientFortune TechAlgorithms of Falsehood: The Challenges of Governing AI-Generated Disinformation - orfonline.orgGoogle News: Generative AIThe Cathedral, the Bazaar, and the Winchester Mystery HouseO'Reilly RadareM Client Adds Generative AI Features - Let's Data ScienceGoogle News: Generative AItrunk/364516d4725fd98c0f2fd2301366409bc54cbc5b: [dtensor][pointwise_ops] removing dead code (#178975)PyTorch ReleasesThe fight on the right over AI - politico.euGNews AI USA
AI NEWS HUBbyEIGENVECTOREigenvector

Axios Hijack Post-Mortem: How to Audit, Pin, and Automate a Defense

DEV Communityby Smyekh David-WestApril 2, 202610 min read0 views
Source Quiz

<p>On March 31, 2026, the <code>axios</code> npm package was compromised via a hijacked maintainer account. Two versions, <code>1.14.1</code> and <code>0.30.4</code>, were weaponised with a malicious phantom dependency called <code>plain-crypto-js</code>. It functions as a Remote Access Trojan (RAT) that executes during the <code>postinstall</code> phase and silently exfiltrates environment variables: AWS keys, GitHub tokens, database credentials, and anything present in your <code>.env</code> at install time.</p> <p>The attack window was approximately 3 hours (00:21 to 03:29 UTC) before the packages were unpublished. A single CI run during that window is sufficient exposure.<br> This post documents the forensic audit and remediation steps performed on a Next.js production stack immediatel

On March 31, 2026, the axios npm package was compromised via a hijacked maintainer account. Two versions, 1.14.1 and 0.30.4, were weaponised with a malicious phantom dependency called plain-crypto-js. It functions as a Remote Access Trojan (RAT) that executes during the postinstall phase and silently exfiltrates environment variables: AWS keys, GitHub tokens, database credentials, and anything present in your .env at install time.

The attack window was approximately 3 hours (00:21 to 03:29 UTC) before the packages were unpublished. A single CI run during that window is sufficient exposure. This post documents the forensic audit and remediation steps performed on a Next.js production stack immediately after the incident.

Why This Happened: The SemVer Caret Problem

Most projects define axios like this:

"axios": "^1.7.9"

Enter fullscreen mode

Exit fullscreen mode

The caret (^) permits any compatible minor or patch release. It means npm install can silently resolve to a newly published 1.14.1 if it satisfies the range. No prompt, no warning, no diff you would notice without inspecting the lockfile.

This is the core tension in SemVer: convenience versus determinism.

The Fix: Pin to the Golden Version

"axios": "1.14.0"

Enter fullscreen mode

Exit fullscreen mode

No caret. No tilde. Exact version.

Why 1.14.0 specifically? It is the last clean release before the March 31 hijack. It also includes the patch for CVE-2025-27152, an SSRF vulnerability fixed in 1.8.2, so you are not trading one vulnerability for another.

Versions to avoid:

  • 1.14.1 — compromised (RAT injected)

  • 0.30.4 — compromised (RAT injected)

Use --save-exact to prevent npm from re-adding the caret on install:

npm install [email protected] --save-exact

Enter fullscreen mode

Exit fullscreen mode

What If Axios Is a Transitive Dependency?

If axios is not a direct dependency in your project but a dependency of another package, pinning it in package.json may not be sufficient. npm can still resolve a different version deeper in the tree.

Use the overrides field in package.json to force the exact version project-wide, regardless of what upstream packages request:

"overrides": {  "axios": "1.14.0" }

Enter fullscreen mode

Exit fullscreen mode

This applies to npm 8.3 and above. For yarn, the equivalent is resolutions. For pnpm, use overrides under the pnpm key in package.json.

Forensic Audit: Were You Hit?

Even if package.json looks correct, package-lock.json may have resolved the malicious metadata during the attack window if npm install ran between 00:21 and 03:29 UTC.

The following checks were performed on the production server via SSH.

1. Lockfile Entropy Check

Run both grep patterns. The first checks for the malicious dependency name and version in the axios context. The second checks for the raw version string regardless of JSON nesting depth, which is relevant in package-lock.json v2 and v3 formats:

# Check 1: Malicious dependency name and axios version context grep -E "plain-crypto-js|axios.*(1\.14\.1|0\.30\.4)" package-lock.json*

Check 2: Raw version string, catches nested lockfile structures

grep -E ""version": "(1.14.1|0.30.4)"" package-lock.json`

Enter fullscreen mode

Exit fullscreen mode

Critical gotcha: run this from the correct directory. A "file not found" error is not a clean result. It means grep never inspected anything. The correct workflow:

user@server:~$ grep -E "plain-crypto-js|axios.*(1\.14\.1|0\.30\.4)" package-lock.json grep: package-lock.json: No such file or directory # Wrong directory. Not a clean result.*

user@server:$ cd project user@server:/project$ grep -E "plain-crypto-js|axios.(1.14.1|0.30.4)" package-lock.json grep: package-lock.json: No such file or directory # Still wrong. Keep navigating.

user@server:/project$ cd frontend user@server:/project/frontend$ grep -E "plain-crypto-js|axios.(1.14.1|0.30.4)" package-lock.json

No output = clean`

Enter fullscreen mode

Exit fullscreen mode

No output from the final command means no malicious indicators found in the lockfile.

2. Filesystem Dropper Verification

The RAT executes via a postinstall script registered by plain-crypto-js. If the directory exists in node_modules, the dropper has already run:

user@server:~/project/frontend$ ls node_modules/plain-crypto-js 2>/dev/null \  && echo "CRITICAL: Malicious package found!" \  || echo "Clean: No dropper found." Clean: No dropper found.

Enter fullscreen mode

Exit fullscreen mode

If either check returns a positive result: rotate all secrets immediately. This includes credentials you might overlook under pressure:

  • Application secrets: database passwords, third-party API keys, cloud provider credentials

  • CI/CD pipeline secrets: NPM_TOKEN, VERCEL_TOKEN, AWS_ACCESS_KEY_ID, and any other tokens injected as environment variables during the build. These are present in the environment at npm install time and are a primary target of this class of attack.

Treat every credential present in the build environment during the compromised install as leaked. Review your cloud provider audit logs for anomalous API calls originating from the build environment before doing anything else.

Automating Prevention in CI/CD

Pinning resolves the immediate exposure. The following three controls prevent recurrence.

A. Lockfile Integrity Enforcement

Use npm ci instead of npm install in your build pipeline. It installs exactly what is recorded in package-lock.json and fails if the two files are out of sync. No silent resolution, no opportunistic upgrades.

For Docker-based builds, this belongs in the Dockerfile:

RUN npm ci

Enter fullscreen mode

Exit fullscreen mode

B. Dependency Scan as a Kill-Switch

Add a pre-build security stage that greps the lockfile for known-malicious strings. If an upstream package is hijacked again, deployment is blocked before a single container is built.

GitLab CI example (shell executor, Docker available on runner):

stages:

  • security
  • deploy

dependency_scan: stage: security tags:

  • oci-runner
  • production rules:
  • if: '$CI_COMMIT_BRANCH == "main"' script:
  • echo "Scanning for malicious dependency versions..."
  • | if grep -E "("axios".*"(1.14.1|0.30.4)"|plain-crypto-js)"
    "$CI_PROJECT_DIR/frontend/package-lock.json"; then echo "SECURITY ALERT: Malicious dependency detected. Blocking deployment." exit 1 fi
  • echo "Malicious version scan passed."
  • echo "Running npm audit..."
  • docker run --rm -v "$CI_PROJECT_DIR/frontend:/app" -w /app node:20-alpine npm audit --audit-level=high`*

Enter fullscreen mode

Exit fullscreen mode

Implementation notes:

  • Do not use -r in the grep. That flag recurses into directories and is incorrect when targeting a specific file.

  • Use $CI_PROJECT_DIR for absolute paths. Relative paths are fragile if any earlier step changes the working directory. This is the same "wrong directory" failure mode demonstrated in the manual audit above.

  • npm audit runs in a throwaway container. If the shell runner does not have Node installed directly, a temporary node:20-alpine container handles it without modifying the runner host.

GitHub Actions equivalent:

- name: Audit for Malicious Axios Versions  run: |  if grep -E "plain-crypto-js|axios.*(1\.14\.1|0\.30\.4)" package-lock.json; then  echo "Security Alert: Malicious dependency detected!"  exit 1  fi*

  • name: npm audit run: npm audit --audit-level=high`

Enter fullscreen mode

Exit fullscreen mode

C. npm audit with Failure Thresholds

npm audit --audit-level=high causes CI to fail on any vulnerability rated High or Critical. It covers a broader class of supply chain issues beyond this specific incident and adds minimal overhead to the pipeline.

npm audit --audit-level=high

Enter fullscreen mode

Exit fullscreen mode

One important caveat: for a zero-day or freshly published hijack, npm audit may not flag the package until a security advisory has been formally ingested into the npm advisory database. During the initial hours of an active attack, the manual grep stage in section B is the more reliable immediate control. The two approaches are complementary, not interchangeable.

D. Egress Restriction on Build Runners

As a systemic long-term control, restrict outbound network traffic from your build environment to a known allowlist of domains. A RAT cannot exfiltrate environment variables if the build server is blocked from making outbound requests to unknown IPs or domains.

Most cloud providers offer security groups or firewall rules at the instance level. For OCI, this is configured via the VCN's security list or network security groups. The build runner should be permitted to reach package registries, your container registry, and your deployment target and nothing else by default.

One layer deeper: blocking standard HTTP/S egress is not sufficient against advanced RATs. DNS exfiltration is a documented technique where data is encoded and tunnelled out via DNS queries, which most firewall rules pass freely. If your threat model warrants it, implement DNS filtering and logging on build runners either via a resolver that blocks non-allowlisted domains, or a logging layer that surfaces anomalous query volumes. This is the logical next control once HTTP/S egress is locked down.

Worth knowing: If supply chain risk is a recurring concern for your stack, look into Socket or Snyk. Both offer malicious package detection that goes beyond standard vulnerability scanning by analysing package behaviour rather than just matching against known CVEs. npm audit tells you about published advisories. These tools flag suspicious patterns before an advisory exists. Both have free tiers suitable for open source projects and solo developers; private commercial repositories require a paid plan.

Summary

Action Priority

Pin axios to 1.14.0(no caret) Immediate

Add overrides in package.json if axios is a transitive dependency Immediate

Grep lockfile for plain-crypto-js and bad versions, from the correct directory Immediate

Check whether node_modules/plain-crypto-js exists Immediate

Rotate all secrets if either check is positive Immediate

Switch CI builds to npm ci

This sprint

Add dependency scan stage to pipeline This sprint

Add npm audit --audit-level=high to CI This sprint

Restrict build runner egress to known domains Next sprint

Implement DNS filtering and logging on build runners Next sprint

Supply chain attacks exploit the trust relationship between developers and the package registry. The plain-crypto-js incident demonstrates that a single compromised maintainer account is sufficient to poison any project that does not lock its dependencies with exact versions.

Pin your versions. Audit your lockfiles. If your build logs show npm install activity on March 31, rotate credentials first and investigate second.

Cover photo by Clint Patterson on Unsplash

Was this article helpful?

Sign in to highlight and annotate this article

AI
Ask AI about this article
Powered by Eigenvector · full article context loaded
Ready

Conversation starters

Ask anything about this article…

Daily AI Digest

Get the top 5 AI stories delivered to your inbox every morning.

Knowledge Map

Knowledge Map
TopicsEntitiesSource
Axios Hijac…modelreleaseavailableversionopen sourceproductDEV Communi…

Connected Articles — Knowledge Graph

This article is connected to other articles through shared AI topics and tags.

Knowledge Graph100 articles · 161 connections
Scroll to zoom · drag to pan · click to open

Discussion

Sign in to join the discussion

No comments yet — be the first to share your thoughts!

More in Releases