NPM Poisoning Analysis — Shai-Hulud Attack Reproduction

Author: Joker & Ccj

Background

Recently, the NPM community has once again experienced a large-scale NPM package poisoning incident, which is highly related to the Shai-Hulud attack incident in September 2025. The malicious code in this NPM package steals sensitive information such as developer keys, API keys, and environment variables, using the keys to create public repositories and upload these stolen sensitive information.

SlowMist( is an independently developed Web3 threat intelligence and dynamic security monitoring tool, MistEye, which responds immediately and swiftly pushes relevant threat intelligence to provide clients with critical security assurance.

![])https://img-cdn.gateio.im/social/moments-159684ebd67ca55d47335ddbd42018c3(

![])https://img-cdn.gateio.im/social/moments-bd2aba046f0a86aca7e1abd2b72e9eed(

At the same time, the backend will save the malicious samples at the first opportunity and calculate their corresponding SHA-256 and other feature values.

![])https://img-cdn.gateio.im/webp-social/moments-0c04f20f1376390bdc04bad915d660b6.webp(

Analysis Process

Taking the @asyncapi/php-template@0.1.1 package as an example, when comparing it with the previous version @asyncapi/php-template@0.1.0, it can be observed that version 0.1.1 has added two js files, namely setup_bun.js and the obfuscated bun_environment.js file.

![])https://img-cdn.gateio.im/webp-social/moments-45994a147ca5cec569400f4833f14468.webp(

A preinstall script has been added to package.json, which will automatically execute setup_bun.js before dependencies are installed.

![])https://img-cdn.gateio.im/webp-social/moments-45e344c5a0d73a61db9f267eae229bc6.webp(

In setup_bun.js, it first checks whether Bun is already installed on the system. If it is not installed, it will automatically download and install Bun from the official website and correctly set the environment variables to locate the Bun executable file.

Finally, execute the bun bun_environment.js file, which is a highly obfuscated malicious file.

![])https://img-cdn.gateio.im/webp-social/moments-44505da1b8a0d007a2a0c1cf3b0472ca.webp(

After partially de-obfuscating the malicious script's code, it can be seen that aL0)( is the main entry function of the entire malicious script. It is roughly evident that this malicious script is designed to steal sensitive information, first checking the runtime environment for the presence of NPM or GitHub credentials. If these credentials are detected, it will use the NPM credentials for supply chain propagation, and all collected system information and sensitive data will ultimately be packaged and uploaded to a GitHub repository controlled by the attacker for further exploitation.

Credential Theft

AWS: The malicious script implements the methods runSecrets)( and listAndRetrieveAllSecrets)(. The runSecrets)( method traverses all accessible cloud access credentials and all possible regions to maximize the scanning range; while listAndRetrieveAllSecrets)( conducts a “deep dive” within specified credentials and regions, enumerating all Secrets and retrieving their latest plaintext content. With both methods combined, the attacker can export all accessible SecretString and SecretBinary from the victim's AWS account at once.

![])https://img-cdn.gateio.im/webp-social/moments-3c33d90aa4bd49b2d8304f07d9cf0c78.webp(

The enumerateValidCredentials)( method is primarily used to comprehensively collect all usable cloud service keys. It will attempt to verify credentials one by one from various sources such as environment variables, configuration files, CLI logins, etc. Any credentials that can be successfully validated will be recorded for use in later stealing of cloud secrets.

![])https://img-cdn.gateio.im/webp-social/moments-18502e3837d4a198101e4f71f742d424.webp(

GCP: Another method implemented in this malicious script, listAndRetrieveAllSecrets)(, is primarily targeting the GCP module. It first lists all the Secrets under the specified Project ID of the GCP project, then directly locates the latest version of each Secret and calls accessSecretVersion to read its plaintext content. Finally, it collects all the retrieved secrets (such as API Keys, database passwords, etc.) one by one.

![])https://img-cdn.gateio.im/webp-social/moments-bad2067511f01dd442e955c89db61dc9.webp(

Azure: Another method implemented in this malicious script called listAndRetrieveAllSecrets)( mainly targets the Azure module. It first scans the entire subscription through the Azure Resource Manager to identify all Key Vaults; then uses the obtained credentials to connect to each Vault one by one; finally enumerates all Secrets within them and calls getSecret to retrieve the plaintext value of each secret.

![])https://img-cdn.gateio.im/social/moments-9176712c5d0ed04eeb1ee93411f8af42(

In the implementation of stealing sensitive information, legitimate security tools are also used to attack the victim. In the extractAndInstall)( method, the binary files of TruffleHog are unpacked and extracted. TruffleHog, originally intended for detecting and verifying leaked confidential information such as API keys and credentials within code repositories, is used by attackers to scan the victim's entire file system.

![])https://img-cdn.gateio.im/webp-social/moments-45e2049fa39e4d26acd79661c664ca21.webp(

) NPM supply chain dissemination

The malicious script implements a function updatePackage###( for NPM supply chain propagation. First, it uses a stolen NPM Token to download the source code of legitimate NPM packages that the victim has publishing rights to, then modifies the package.json file by inserting a malicious preinstall script command in the scripts field. Meanwhile, it places the malicious script into the package and automatically increments the package version number by 1 to trigger the user's automatic update, pushing the NPM package with the malicious script to the official NPM repository.

![])https://img-cdn.gateio.im/social/moments-f2c1d619c8b8a125a018a4990e47e144(

) Backdoor and C2

After stealing the information, a randomly named repository will be created under the account using the stolen GitHub Token, and a registration token will be obtained. The victim's computer will be disguised as a self-hosted GitHub Actions Runner for that repository. Subsequently, the attacker will implant malicious workflows in the repository, causing any triggered Actions tasks to execute on the victim's machine, thereby achieving remote code execution.

![]###https://img-cdn.gateio.im/webp-social/moments-547cfd5eb9ee4614a975d1f574583495.webp(

And upload the stolen information, which has been double base64 encoded, to the created repository, the descriptions of which are all “Sha1-Hulud: The Second Coming.”.

![])https://img-cdn.gateio.im/webp-social/moments-6bad80b5f904d7c25fa993600ff2a710.webp(

After decryption, sensitive data leaked by the user can be seen.

![])https://img-cdn.gateio.im/social/moments-73bf3f27df82dfd50c02ff7c42e746af(

![])https://img-cdn.gateio.im/webp-social/moments-aefb641fee19ee0ad471234e3d5aa081.webp(

![])https://img-cdn.gateio.im/social/moments-ea2062526e3489a6cfd6fcbebd94605c(

Summary

The recent NPM repository poisoning combines worms and long-term persistence of self-hosted runners, utilizing TruffleHog for attacks. The Slow Fog security team recommends that developers adopt a dependency version locking strategy when building and releasing new iterations. If a dependency has necessary security or functional updates, they should be updated through a strict internal security audit process, and the locked version should be updated synchronously to avoid introducing new risks through blind updates.

View Original
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Reward
  • Comment
  • Repost
  • Share
Comment
0/400
No comments
  • Pin
Trade Crypto Anywhere Anytime
qrCode
Scan to download Gate App
Community
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)