The Open Source Supply Chain Crisis: Architecting Beyond Trusted Dependencies

The Open Source Supply Chain Crisis: Architecting Beyond Trusted Dependencies

Examining recent Axios and Claude Code leaks reveals fundamental flaws in how architects consume NPM and public registries. Strategies for securing build pipelines against poisoning and supply-chain attacks.

The modern software architect operates under a convenient fiction: that the dependencies pulled from NPM, PyPI, or Maven Central are inert, trustworthy building blocks rather than live attack surfaces. That illusion shattered on March 31, 2026, when axios, the JavaScript HTTP client with over 100 million weekly downloads, became a delivery mechanism for cross-platform remote access trojans. Within hours, we learned that Claude Code had leaked its source via source maps left in their NPM registry. The message is clear: your build pipeline is a target, and the “trusted” dependencies you’re installing are potential weapons.

The Axios Compromise: A Masterclass in Supply Chain Sophistication

This wasn’t a typosquatting attack or a malicious fork buried in a dependency tree. The attacker compromised the npm account of jasonsaayman, the lead maintainer of axios, changed the registered email to ifstap@proton.me, and published two poisoned versions (1.14.1 and 0.30.4) directly to the registry. The sophistication lies in what they didn’t do: they modified exactly one line in package.json.

The malicious versions added a “phantom dependency”, plain-crypto-js@4.2.1, which is never imported or required anywhere in the axios source code. Its sole purpose is to execute a postinstall script that deploys a cross-platform RAT. Within 1.1 seconds of npm install, the dropper contacts sfrclak.com:8000 and delivers platform-specific payloads: a Mach-O binary disguised as com.apple.act.mond on macOS, a PowerShell script masquerading as Windows Terminal (wt.exe) on Windows, and a Python script at /tmp/ld.py on Linux.

The anti-forensics are surgical. After execution, the malware deletes itself, swaps the malicious package.json with a clean stub renamed from package.md, and detaches from the process tree using nohup. A developer inspecting node_modules/plain-crypto-js after the fact sees a completely legitimate package reporting version 4.2.0, not the malicious 4.2.1 they were told to hunt for.

The forensic smoking gun: The presence of the plain-crypto-js directory at all. This package never appeared in any legitimate axios release. If it exists in your node_modules, the dropper executed, regardless of what npm list reports.

The OIDC Bypass Signal

Legitimate axios releases are published via GitHub Actions using npm’s OIDC Trusted Publisher mechanism, cryptographically binding the release to a verified workflow. The malicious versions broke this pattern entirely:

// Legitimate axios@1.14.0
"_npmUser": {
  "name": "GitHub Actions", 
  "email": "npm-oidc-no-reply@github.com", 
  "trustedPublisher": {
    "id": "github", 
    "oidcConfigId": "oidc:9061ef30-3132-49f4-b28c-9338d192a1a9"
  }
}

// Malicious axios@1.14.1
"_npmUser": {
  "name": "jasonsaayman", 
  "email": "ifstap@proton.me"
  // No trustedPublisher, no gitHead
}

There is no corresponding GitHub commit or tag for 1.14.1. The release exists only on npm, published manually with a stolen long-lived classic token, bypassing the ephemeral, workflow-scoped OIDC tokens that legitimate releases use.

Claude Code’s Source Map Leak: When Build Artifacts Attack

While axios was being weaponized, Claude Code (Anthropic’s agentic coding tool) suffered a different supply chain failure: its source code was leaked via source map files (*.map) included in their NPM registry packages. These maps, designed to map minified code back to source for debugging, contained the full TypeScript source, internal API endpoints, and implementation details.

This reveals a fundamental architectural blind spot: build artifacts are code too. Source maps, debug symbols, and unminified bundles often contain more sensitive information than the source repositories themselves. When you publish to NPM, you’re not just shipping the code that runs, you’re shipping the metadata that explains exactly how it works.

The Architecture of Distrust

These incidents expose the fragility of our current dependency models. We are witnessing the collapse of reliance on single-maintainer critical infrastructure, where one compromised account can poison millions of systems. The axios attack follows the same pattern we’ve seen with maintainers abandoning open source repositories and corporate consolidations threatening open source trust: centralized control points becoming single points of failure.

The “supply chain” metaphor implies a linear pipeline with verified checkpoints. The reality is a chaotic bazaar where:

  1. Postinstall scripts execute arbitrary code with the user’s privileges before the install command even returns
  2. Version resolution is transitive and automatic, pulling in dependencies of dependencies without explicit consent
  3. Registry metadata is trusted implicitly, despite having no cryptographic linkage to source code provenance
  4. Self-destructing malware leaves no artifacts for post-incident analysis

Concrete Defenses for Software Architects

If you’re still running npm install in CI/CD without constraints, you’re gambling with your secrets. Here are the technical controls that would have blocked this attack:

1. Lockfile Enforcement with Immutable Installs

The plain-crypto-js dependency was live for less than 24 hours before being pulled into axios. If your CI uses npm ci (which respects package-lock.json exactly) rather than npm install (which updates ranges), you were protected, provided your lockfile was committed before March 31, 2026.

# In CI/CD pipelines - always use ci, never install
npm ci --ignore-scripts

The --ignore-scripts flag prevents postinstall hooks from executing entirely. This would have neutralized the setup.js dropper before it could contact the C2 server.

2. Package Age Gating

Malicious packages often have a “freshness” problem. The attacker published a clean decoy version (4.2.0) 18 hours before the malicious payload (4.2.1) to build registry history. Configure your package manager to reject packages newer than a cooldown period:

npm config set min-release-age 3

Tools like Aikido Safe Chain enforce this at the registry level, blocking packages that haven’t survived a 48-hour scrutiny window.

3. Runtime Network Isolation

StepSecurity’s Harden-Runner detected the C2 callback to sfrclak.com:8000 within seconds by monitoring outbound connections from CI runners. The process tree revealed the full kill chain: npm → sh → node → sh → curl/nohup, with the nohup process orphaned to PID 1 (init) to evade detection.

Implement egress allowlisting in your build environments. If your CI doesn’t need to reach arbitrary HTTP endpoints, block them. The malware’s execSync calls would fail silently, but the install would complete without compromise.

4. Phantom Dependency Detection

Scan for dependencies that appear in package.json but have zero imports in the source code. The plain-crypto-js package was never imported by axios, a high-confidence indicator of compromise. Tools like Socket and Snyk perform this analysis automatically.

5. Source Map Sanitization

Before publishing to NPM, strip source maps from production packages:

// package.json
"files": [
  "dist/**/*", 
  "!dist/**/*.map"
]

Or configure your build tool to not generate them for releases. The risk of risk of integrating unverified open source releases includes the metadata those releases carry.

The Indicators You Should Hunt For

If you suspect compromise, check for these specific artifacts:

Malicious Packages:
axios@1.14.1 (SHA1: 2553649f232204966871cea80a5d0d6adc700ca)
axios@0.30.4 (SHA1: d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71)
plain-crypto-js@4.2.1 (SHA1: 07d889e2dadce6f3910dcbc253317d28ca61c766)

Network Indicators:
– C2 Domain: sfrclak.com (IP: 142.11.206.73)
– Port: 8000
– Campaign Path: /6202033

File System Artifacts:
– macOS: /Library/Caches/com.apple.act.mond
– Windows: %PROGRAMDATA%\wt.exe (persistent PowerShell copy)
– Linux: /tmp/ld.py

If you find wt.exe in ProgramData or com.apple.act.mond in your Library/Caches, treat the system as fully compromised. Do not attempt to clean in place, rebuild from a known-good state and rotate all credentials, including npm tokens, AWS keys, and any secrets accessible during the install window.

Conclusion: Trust But Verify (Actually, Just Verify)

The axios compromise and Claude Code leak mark a turning point in how we must architect software systems. The “trust on first use” model of package management is dead. We can no longer assume that a package with 100 million downloads and a reputable maintainer is safe, we must verify the cryptographic provenance of every artifact, isolate our build environments, and treat dependency installation as a privileged operation requiring sandboxing.

The supply chain isn’t just under attack, it has become the primary attack vector. Architects who fail to implement zero-trust dependency models aren’t just taking risks, they’re building targets. Start with --ignore-scripts, enforce lockfile immutability, and monitor your build pipelines like you monitor production. Because in 2026, the malware isn’t coming through your firewall. It’s coming through npm install.

Share:

Related Articles