AsyncAPI npm Packages With 2M Weekly Downloads Compromised via GitHub Actions

In Cybersecurity News - Original News Source is cybersecuritynews.com by Blog Writer

Spread the love

A supply chain compromise has placed AsyncAPI npm packages at the center of a developer security incident.

Five trojanized releases, with roughly 2.9 million combined weekly downloads, were published after an attacker gained access to an npm publishing token.

The incident creates risk for development workstations, build servers, and environments that loaded the affected modules.

The attack began in the AsyncAPI generator repository, where a GitHub Actions workflow used the pull_request_target trigger. This configuration allowed repository secrets to be exposed when code from an external pull request was checked out.

The attacker opened multiple pull requests and used one to send the npm token to rentry.co before publishing altered packages.

Aikido analysts identified the malicious releases on July 14 and traced the campaign from a workflow weakness to a persistent remote-access implant. 

Aikido said in a report shared with Cyber Security News (CSN) that importing an affected package, rather than installing it, could launch the infection chain.

That distinction makes builds and development activity a potential exposure point. The injected code downloaded an encrypted Node.js loader from IPFS, saved it as sync.js, and ran it in a detached process.

The final payload established persistence and offered attackers a remote shell capable of collecting data and running commands. Although credential theft and self-spreading code existed in the bundle, those functions were disabled in the observed build.

GitHub Actions Breach Backdoors AsyncAPI Packages

The compromised versions were asyncapi-specs 6.11.2 and 6.11.2-alpha.1, asyncapi-generator 3.3.1, asyncapi-generator-helpers 1.1.1, and asyncapi-generator-components 0.7.1.

The malicious code was embedded in ordinary runtime modules, including schema exports, validation logic, utility code, and error handling. As a result, a standard require operation could trigger the downloader without an npm lifecycle script.

The two downloader variants retrieved different IPFS objects and placed their payload in a per-user NodeJS data directory.

On macOS, the path used Library/Application Support/NodeJS; on Windows it used LOCALAPPDATA; and on Linux it used .local/share/NodeJS.

The loader then decrypted and evaluated a second-stage component designed to survive beyond the original package execution.

Researchers found that the implant generated a cryptographic key pair, maintained a lock file, and attempted to persist across operating systems.

It added commands to shell startup files on macOS, created a Run registry value on Windows, and wrote a user service file on Linux.

The Linux service appears likely to fail because its execution command lacks a shell wrapper, but the artifacts are still useful evidence during incident response.

Remote Shell Raises Response Stakes

The malware contacted an HTTP command-and-control server about every 30 seconds and sent encrypted beacons.

Even with reconnaissance switched off, those messages contained redacted previews of environment information and checked for configuration files tied to developer tools.

More significantly, the implant could execute shell commands, giving an operator a route to collect sensitive material or move deeper into a network.

Several configuration values appeared to portray the payload as a canary, including safeMode and a five percent setting.

Code analysis showed that these settings did not meaningfully restrict execution: persistence was enabled through a different toggle, and no victim-selection path used the percentage.

The use of HTTP also introduced an additional concern because an attacker positioned on the network path could inject plaintext commands when no encrypted command bundle was present.

Organizations should downgrade to asyncapi-specs 6.11.1, asyncapi-generator 3.3.0, asyncapi-generator-helpers 1.1.0, and asyncapi-generator-components 0.7.0.

They should remove the compromised releases from manifests, lockfiles, caches, internal mirrors, and build images.

Teams should hunt for systems that imported the modules, isolate suspected hosts while preserving volatile data, and examine detached Node processes and persistence artifacts.

Credentials accessible from a developer device or build host should be treated as exposed. Teams should rotate npm tokens, source-control access, cloud credentials, CI/CD secrets, SSH and signing keys, and browser sessions from a clean machine, and rebuild compromised systems.

Network investigations should also review connections to the listed command server, IPFS, Nostr, Ethereum RPC, DHT, and mDNS activity associated with Node processes.

Indicators of Compromise (IoCs):-

Type Indicator Description
Compromised package asyncapi-specs 6.11.2 Trojanized npm release; SHA-256: 9b2e65db653ca8575c9b10eefb9a80c6006404812c2ec212bf5675e3c690233b 
Compromised package asyncapi-specs 6.11.2-alpha.1 Trojanized npm release; SHA-256: d425e4583cc6185d41e95c45eda00550045a5d1919b9a012236a4520d009dbd7 
Compromised package asyncapi-generator 3.3.1 Trojanized npm release; SHA-256: bfaeb987faa6de2b5a5eb63b1233d055215b09b0349a9394f2175fd7cdf385e4 
Compromised package asyncapi-generator-helpers 1.1.1 Trojanized npm release; SHA-256: 34014776d3d3ff11bc4439b02fd7ac0f02a887eb3a052eeafff236e2f6db8ad1 
Compromised package asyncapi-generator-components 0.7.1 Trojanized npm release; SHA-256: 082d733db0687dcd768104972b065d4b58cb1e6043688c6c20fa3702337f36ab 
IPFS CID Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf Specs-family encrypted loader object 
IPFS CID QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9 Generator-family encrypted loader object 
Payload hash f873941d1907a97dc6c718fdecf59fd7d91f3f8212da2f7e5314b878b88bdc0b SHA-256 of recovered specs stage-three payload 
Payload hash 9e214f38537e69bf51c7fa1ddd35ae495e9cb897231ec010baf9e4f29407ee9a SHA-256 of recovered generator-family stage-three payload 
C2 server 85.137.53.71:8080 HTTP beacon and command channel 
Network ports 85.137.53.71:808185.137.53.71:8091 Upload and proxy-management services 
Network range 85.137.53.0/24 Associated RIPE network block 
Domain rentry.co Destination used to exfiltrate the npm publishing token 
Ethereum contract 0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710 Contract used for service-address and update records, chain ID 1 
Nostr relays wss://relay.damus.iowss://relay.nostr.com Address and signed update-record infrastructure 
DHT bootstrap nodes router.bittorrent.com:6881dht.transmissionbt.com:6881 Peer-discovery infrastructure 
Dropped file sync.js Loader written to the per-user NodeJS data directory 
Lock file .config/miasma/runnode.lock Prevents duplicate implant instances 
macOS identity file Library/Application Support/com.apple.spotlight/index-v2.cache Disguised implant identity path 
Linux identity file .cache/mesa/shadercache/glcache.bin Disguised implant identity path 
Windows identity file HOME.dat Disguised implant identity path 
Linux persistence .config/systemd/user/miasma-monitor.service User-level persistence artifact 
Windows persistence miasma-monitor Registry Run value used for persistence 
Public key 0432fa4ba871877d94081fe83323fa24dfa1491e9de8725cbab7b734de9e9be3b233ef6742fd6264437c9532223d687b05fa540b70af6a516b8539af84d0eeb48e Attacker secp256k1 public key 

Note: IP addresses and domains are intentionally defanged (e.g., [.]) to prevent accidental resolution or hyperlinking. Re-fang only within controlled threat intelligence platforms such as MISP, VirusTotal, or your SIEM.

Help your security team focus on the that matter most. Use ANY.RUN Threat Intelligence Feeds to automate enrichment and improve detection accuracy.