<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Supply Chain Attack on ICE-ICE-BEAR-BLOG</title><link>https://ice-ice-bear.github.io/tags/supply-chain-attack/</link><description>Recent content in Supply Chain Attack on ICE-ICE-BEAR-BLOG</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Wed, 01 Apr 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://ice-ice-bear.github.io/tags/supply-chain-attack/index.xml" rel="self" type="application/rss+xml"/><item><title>2026 npm Supply Chain Attacks — axios, LiteLLM, and the Lessons Learned</title><link>https://ice-ice-bear.github.io/posts/2026-04-01-npm-supply-chain-attacks/</link><pubDate>Wed, 01 Apr 2026 00:00:00 +0900</pubDate><guid>https://ice-ice-bear.github.io/posts/2026-04-01-npm-supply-chain-attacks/</guid><description>&lt;img src="https://ice-ice-bear.github.io/" alt="Featured image of post 2026 npm Supply Chain Attacks — axios, LiteLLM, and the Lessons Learned" /&gt;&lt;p&gt;In the last week of March 2026, the open source ecosystem was hit by a cascade of supply chain attacks. axios — with weekly downloads over 100 million — was compromised on npm. LiteLLM — with 97 million monthly downloads — was breached on PyPI. And Claude Code&amp;rsquo;s source code was exposed through npm &lt;code&gt;.map&lt;/code&gt; files. This post covers the technical details of each incident, the common patterns they share, and what you can do about it.&lt;/p&gt;
&lt;h2 id="1-the-axios-supply-chain-attack-2026-03-31"&gt;1. The axios Supply Chain Attack (2026-03-31)
&lt;/h2&gt;&lt;h3 id="how-it-happened"&gt;How It Happened
&lt;/h3&gt;&lt;p&gt;The npm account of axios lead maintainer &lt;strong&gt;jasonsaayman&lt;/strong&gt; was taken over. The attacker changed the account email to a ProtonMail address (&lt;code&gt;ifstap@proton.me&lt;/code&gt;), then used a &lt;strong&gt;long-lived npm token&lt;/strong&gt; to bypass GitHub Actions CI/CD entirely and publish directly via the npm CLI.&lt;/p&gt;
&lt;p&gt;Both release branches (1.x and 0.x) were compromised within &lt;strong&gt;39 minutes&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Infected version&lt;/th&gt;
 &lt;th&gt;Safe version&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;axios@1.14.1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;axios@1.14.0&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;axios@0.30.4&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;axios@0.30.3&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The malicious dependency &lt;code&gt;plain-crypto-js@4.2.1&lt;/code&gt; had been pre-staged on npm &lt;strong&gt;18 hours before the attack&lt;/strong&gt; under account &lt;code&gt;nrwise&lt;/code&gt; (&lt;code&gt;nrwise@proton.me&lt;/code&gt;). Pre-built payloads for three operating systems made this a highly premeditated operation.&lt;/p&gt;
&lt;h3 id="what-the-malware-did"&gt;What the Malware Did
&lt;/h3&gt;&lt;p&gt;The infected axios versions inject a fake dependency called &lt;code&gt;plain-crypto-js@4.2.1&lt;/code&gt;. This package is not imported anywhere in the axios source — its sole purpose is to deploy a &lt;strong&gt;cross-platform RAT&lt;/strong&gt; (Remote Access Trojan) via the &lt;code&gt;postinstall&lt;/code&gt; script.&lt;/p&gt;
&lt;h4 id="platform-specific-payloads"&gt;Platform-Specific Payloads
&lt;/h4&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;OS&lt;/th&gt;
 &lt;th&gt;Behavior&lt;/th&gt;
 &lt;th&gt;Artifact file&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;macOS&lt;/td&gt;
 &lt;td&gt;Downloads trojan from C2 via AppleScript&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/Library/Caches/com.apple.act.mond&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Windows&lt;/td&gt;
 &lt;td&gt;Drops executable in ProgramData&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;%PROGRAMDATA%\wt.exe&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Linux&lt;/td&gt;
 &lt;td&gt;Executes Python script&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;/tmp/ld.py&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="self-concealment-mechanism"&gt;Self-Concealment Mechanism
&lt;/h4&gt;&lt;p&gt;After execution, the malware deletes itself and replaces &lt;code&gt;package.json&lt;/code&gt; with a clean version pre-prepared as &lt;code&gt;package.md&lt;/code&gt;, evading forensic detection. Even opening &lt;code&gt;node_modules&lt;/code&gt; after infection would show everything as normal.&lt;/p&gt;
&lt;h3 id="attack-flow"&gt;Attack Flow
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD
 A["npm account takeover&amp;lt;br/&amp;gt;jasonsaayman"] --&gt; B["Email changed&amp;lt;br/&amp;gt;ifstap@proton.me"]
 B --&gt; C["Long-lived npm token&amp;lt;br/&amp;gt;bypasses CI/CD"]
 C --&gt; D["plain-crypto-js@4.2.1&amp;lt;br/&amp;gt;pre-staged 18 hours earlier"]
 C --&gt; E["Publish axios@1.14.1"]
 C --&gt; F["Publish axios@0.30.4"]
 E --&gt; G["npm install runs"]
 F --&gt; G
 G --&gt; H["postinstall script executes"]
 H --&gt; I["Platform detection"]
 I --&gt; J["macOS: AppleScript RAT"]
 I --&gt; K["Windows: drop wt.exe"]
 I --&gt; L["Linux: run ld.py"]
 J --&gt; M["C2 communication&amp;lt;br/&amp;gt;sfrclak.com:8000"]
 K --&gt; M
 L --&gt; M
 M --&gt; N["Replace with package.md&amp;lt;br/&amp;gt;self-concealment"]

 style A fill:#ff6b6b,color:#fff
 style M fill:#ff6b6b,color:#fff
 style N fill:#ffa94d,color:#fff&lt;/pre&gt;&lt;h3 id="indicators-of-compromise-ioc"&gt;Indicators of Compromise (IOC)
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Item&lt;/th&gt;
 &lt;th&gt;Value&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;C2 domain&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;sfrclak.com&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;C2 IP&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;142.11.206.73&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;C2 port&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;8000&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Malicious npm account&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;nrwise&lt;/code&gt; (&lt;code&gt;nrwise@proton.me&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Malicious package&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;plain-crypto-js@4.2.1&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Compromised account email&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ifstap@proton.me&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="additional-infected-packages"&gt;Additional Infected Packages
&lt;/h3&gt;&lt;p&gt;Additional packages distributing the same malware were identified:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@shadanai/openclaw&lt;/code&gt; (versions 2026.3.28-2, 2026.3.28-3, 2026.3.31-1, 2026.3.31-2)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@qqbrowser/openclaw-qbot@0.0.130&lt;/code&gt; (contains a tampered &lt;code&gt;axios@1.14.1&lt;/code&gt; in &lt;code&gt;node_modules&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="incident-response-timeline"&gt;Incident Response Timeline
&lt;/h3&gt;&lt;p&gt;The situation was shared in real time in GitHub issue &lt;a class="link" href="https://github.com/axios/axios/issues/10604" target="_blank" rel="noopener"
 &gt;axios/axios#10604&lt;/a&gt;. Collaborator DigitalBrainJS was unable to act directly because jasonsaayman held higher permissions. The situation was only resolved after requesting the npm team to revoke all tokens.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2-the-litellm-supply-chain-attack-2026-03-24"&gt;2. The LiteLLM Supply Chain Attack (2026-03-24)
&lt;/h2&gt;&lt;h3 id="background-the-teampcp-campaign"&gt;Background: The TeamPCP Campaign
&lt;/h3&gt;&lt;p&gt;This incident was part of a chained supply chain attack campaign by the &lt;strong&gt;TeamPCP&lt;/strong&gt; hacking group, which started with security scanner &lt;strong&gt;Trivy&lt;/strong&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Date&lt;/th&gt;
 &lt;th&gt;Target&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;2026-02-28&lt;/td&gt;
 &lt;td&gt;Initial Trivy repository compromise&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2026-03-19&lt;/td&gt;
 &lt;td&gt;76 Trivy GitHub Actions tags tampered&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2026-03-20&lt;/td&gt;
 &lt;td&gt;28+ npm packages taken over&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2026-03-21&lt;/td&gt;
 &lt;td&gt;Checkmarx KICS GitHub Action compromised&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;2026-03-24&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;LiteLLM PyPI package compromised&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;LiteLLM was using Trivy in CI/CD security scanning &lt;strong&gt;without version pinning&lt;/strong&gt;. When the tampered Trivy ran, PyPI publish tokens were transferred to the attacker.&lt;/p&gt;
&lt;h3 id="attack-method"&gt;Attack Method
&lt;/h3&gt;&lt;p&gt;The attacker uploaded &lt;code&gt;litellm&lt;/code&gt; v1.82.7 (10:39 UTC) and v1.82.8 (10:52 UTC) directly using the stolen PyPI token.&lt;/p&gt;
&lt;p&gt;The core attack vector was a &lt;code&gt;.pth&lt;/code&gt; file. Python&amp;rsquo;s &lt;code&gt;.pth&lt;/code&gt; files, when placed in &lt;code&gt;site-packages&lt;/code&gt;, &lt;strong&gt;execute automatically when the Python interpreter starts&lt;/strong&gt; — meaning any Python execution in that environment triggers the malicious code, even without &lt;code&gt;import litellm&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# litellm_init.pth (34,628 bytes) — one-liner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;import base64; exec(base64.b64decode(&amp;#39;...&amp;#39;))&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The decoded payload was a &lt;strong&gt;332-line credential harvesting script&lt;/strong&gt; that collected:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SSH keys (RSA, Ed25519, ECDSA, DSA, and all other types)&lt;/li&gt;
&lt;li&gt;Cloud credentials — AWS/GCP/Azure (including instance metadata)&lt;/li&gt;
&lt;li&gt;Kubernetes service account tokens and secrets&lt;/li&gt;
&lt;li&gt;PostgreSQL, MySQL, Redis, MongoDB config files&lt;/li&gt;
&lt;li&gt;Cryptocurrency wallets — Bitcoin, Ethereum, Solana, and others&lt;/li&gt;
&lt;li&gt;Shell history — &lt;code&gt;.bash_history&lt;/code&gt;, &lt;code&gt;.zsh_history&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Collected data was double-encrypted (AES-256-CBC + RSA-4096) and sent to &lt;code&gt;https://models.litellm.cloud/&lt;/code&gt; — a typosquatting domain registered one day before the attack.&lt;/p&gt;
&lt;h3 id="scale-of-impact"&gt;Scale of Impact
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Monthly downloads&lt;/strong&gt;: ~97 million (~3.4 million/day)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PyPI exposure window&lt;/strong&gt;: ~3 hours&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud environment prevalence&lt;/strong&gt;: ~36% (Wiz Research analysis)&lt;/li&gt;
&lt;li&gt;Affected downstream projects: DSPy (Stanford), CrewAI, Google ADK, browser-use, and others&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="how-it-was-caught"&gt;How It Was Caught
&lt;/h3&gt;&lt;p&gt;Ironically, the attacker&amp;rsquo;s own bug triggered the discovery. The &lt;code&gt;.pth&lt;/code&gt; file spawned a child process on every Python startup, and each child would also re-execute the &lt;code&gt;.pth&lt;/code&gt;, creating a &lt;strong&gt;fork bomb&lt;/strong&gt; — memory would rapidly exhaust. FutureSearch.ai&amp;rsquo;s Callum McMahon noticed the anomaly and filed an issue, but the attacker deployed a botnet of 73 accounts to flood the issue with 88 spam comments in 102 seconds trying to bury it.&lt;/p&gt;
&lt;p&gt;Andrej Karpathy called this incident &lt;strong&gt;&amp;ldquo;software horror.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="how-to-check-for-litellm-infection"&gt;How to Check for LiteLLM Infection
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check installed version — 1.82.7 or 1.82.8 means infected&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip show litellm &lt;span class="p"&gt;|&lt;/span&gt; grep Version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check for .pth file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find / -name &lt;span class="s2"&gt;&amp;#34;litellm_init.pth&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check for backdoor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls ~/.config/sysmon/sysmon.py 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls ~/.config/systemd/user/sysmon.service 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Kubernetes environment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pods -n kube-system &lt;span class="p"&gt;|&lt;/span&gt; grep node-setup
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="3-claude-code-source-code-exposure"&gt;3. Claude Code Source Code Exposure
&lt;/h2&gt;&lt;p&gt;Around the same time, another npm security incident was reported. The source code of Anthropic&amp;rsquo;s &lt;strong&gt;Claude Code CLI&lt;/strong&gt; was found to be &lt;strong&gt;fully recoverable&lt;/strong&gt; through &lt;code&gt;.map&lt;/code&gt; files (source maps) included in the npm package.&lt;/p&gt;
&lt;p&gt;This was not a malicious attack, but it illustrates that including &lt;code&gt;.map&lt;/code&gt; files in an npm package publish exposes the original source behind any obfuscated or bundled code. It is a reminder of the importance of configuring &lt;code&gt;.npmignore&lt;/code&gt; or the &lt;code&gt;files&lt;/code&gt; field properly.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="4-common-lessons-and-defenses"&gt;4. Common Lessons and Defenses
&lt;/h2&gt;&lt;h3 id="the-pattern-across-all-three-incidents"&gt;The Pattern Across All Three Incidents
&lt;/h3&gt;&lt;p&gt;All three incidents abused &lt;strong&gt;trust in package registries (npm/PyPI)&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Pattern&lt;/th&gt;
 &lt;th&gt;axios&lt;/th&gt;
 &lt;th&gt;LiteLLM&lt;/th&gt;
 &lt;th&gt;Claude Code&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Attack vector&lt;/td&gt;
 &lt;td&gt;npm account takeover&lt;/td&gt;
 &lt;td&gt;PyPI token theft (via Trivy)&lt;/td&gt;
 &lt;td&gt;Source map not excluded&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Registry&lt;/td&gt;
 &lt;td&gt;npm&lt;/td&gt;
 &lt;td&gt;PyPI&lt;/td&gt;
 &lt;td&gt;npm&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CI/CD bypass&lt;/td&gt;
 &lt;td&gt;Direct publish&lt;/td&gt;
 &lt;td&gt;Direct publish&lt;/td&gt;
 &lt;td&gt;N/A&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Malicious behavior&lt;/td&gt;
 &lt;td&gt;postinstall RAT&lt;/td&gt;
 &lt;td&gt;.pth auto-execution&lt;/td&gt;
 &lt;td&gt;Source exposure&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Concealment attempt&lt;/td&gt;
 &lt;td&gt;Replace with package.md&lt;/td&gt;
 &lt;td&gt;Botnet spam&lt;/td&gt;
 &lt;td&gt;None&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="immediate-response-checklist"&gt;Immediate Response Checklist
&lt;/h3&gt;&lt;h4 id="npm-axios"&gt;npm (axios)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Check for infected version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm ls axios
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. Pin to safe version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install axios@1.14.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. Commit lockfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add package-lock.json &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit -m &lt;span class="s2"&gt;&amp;#34;fix: pin axios to safe version&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4. Security audit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm audit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 5. Check for IOC network connections&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Look for outbound connections to sfrclak.com or 142.11.206.73&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="pypi-litellm"&gt;PyPI (LiteLLM)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Pin to safe version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install &lt;span class="s2"&gt;&amp;#34;litellm&amp;lt;=1.82.6&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. If infected, rotate all secrets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SSH keys, AWS/GCP/Azure credentials, DB passwords, API keys — replace everything&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="long-term-defenses"&gt;Long-Term Defenses
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pin versions&lt;/strong&gt;: Use exact versions instead of &lt;code&gt;^&lt;/code&gt; or &lt;code&gt;~&lt;/code&gt;. Always commit lockfiles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block postinstall scripts&lt;/strong&gt;: Consider &lt;code&gt;npm install --ignore-scripts&lt;/code&gt; in CI/CD.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Require MFA&lt;/strong&gt;: Enable TOTP-based 2FA on npm/PyPI maintainer accounts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manage token lifetimes&lt;/strong&gt;: Use OIDC-based short-lived tokens instead of long-lived ones. Rotate regularly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin CI/CD tool versions&lt;/strong&gt;: LiteLLM&amp;rsquo;s unversioned Trivy use was the root cause. Security scanners are not exempt.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove source maps&lt;/strong&gt;: Audit whether &lt;code&gt;.map&lt;/code&gt; files are included in production npm packages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor dependencies&lt;/strong&gt;: Continuously watch your supply chain with Socket, Snyk, or &lt;code&gt;npm audit&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="takeaways"&gt;Takeaways
&lt;/h2&gt;&lt;p&gt;The simultaneous npm and PyPI incidents in a single week reveal some uncomfortable truths.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First, maintainers are a single point of failure.&lt;/strong&gt; In the axios case, one compromised account infected two release branches in 39 minutes, and other collaborators lacked the permissions to do anything. In a world where OIDC-based publishing is not yet widely adopted, long-lived tokens are ticking time bombs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Second, security tools themselves become attack vectors.&lt;/strong&gt; In the LiteLLM incident, security scanner Trivy became the entry point for the attack. Installing tools without version pins — like &lt;code&gt;apt-get install -y trivy&lt;/code&gt; — is trading convenience for security.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Third, attackers are becoming more sophisticated.&lt;/strong&gt; Pre-staging payloads 18 hours ahead, self-concealment mechanisms, deploying a 73-account botnet to bury GitHub issues, using AI agents for vulnerability scanning — supply chain attacks are industrializing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The bottom line&lt;/strong&gt;: when you run &lt;code&gt;npm install&lt;/code&gt; or &lt;code&gt;pip install&lt;/code&gt;, you are extending trust to thousands of maintainers. Basic hygiene measures — committing lockfiles, pinning versions, &lt;code&gt;--ignore-scripts&lt;/code&gt;, and rotating tokens — have never mattered more.&lt;/p&gt;</description></item></channel></rss>