RL Blog

Topics

All Blog PostsAppSec & Supply Chain SecurityDev & DevSecOpsProducts & TechnologySecurity OperationsThreat Research
Why RL Built Spectra Assure Community

Why RL Built Spectra Assure Community

We set out to help dev and AppSec teams secure the village: OSS dependencies, malware, more. Learn how.

Read More about Why RL Built Spectra Assure Community
Why RL Built Spectra Assure Community

Follow us

XX / TwitterLinkedInLinkedInFacebookFacebookInstagramInstagramYouTubeYouTubeblueskyBluesky

Subscribe

Get the best of RL Blog delivered to your in-box weekly. Stay up to date on key trends, analysis and best practices across threat intelligence and software supply chain security.

ReversingLabs: The More Powerful, Cost-Effective Alternative to VirusTotalSee Why
Skip to main content
Contact UsSupportLoginBlogCommunity
reversinglabsReversingLabs: Home
Solutions
Secure Software OnboardingSecure Build & ReleaseProtect Virtual MachinesIntegrate Safe Open SourceGo Beyond the SBOM
Increase Email Threat ResilienceDetect Malware in File Shares & StorageAdvanced Malware Analysis SuiteICAP Enabled Solutions
Scalable File AnalysisHigh-Fidelity Threat IntelligenceCurated Ransomware FeedAutomate Malware Analysis Workflows
Products & Technology
Spectra Assure®Software Supply Chain SecuritySpectra DetectHigh-Speed, High-Volume, Large File AnalysisSpectra AnalyzeIn-Depth Malware Analysis & Hunting for the SOCSpectra IntelligenceAuthoritative Reputation Data & Intelligence
Spectra CoreIntegrations
Industry
Energy & UtilitiesFinanceHealthcareHigh TechPublic Sector
Partners
Become a PartnerValue-Added PartnersTechnology PartnersMarketplacesOEM Partners
Alliances
Resources
BlogContent LibraryCybersecurity GlossaryConversingLabs PodcastEvents & WebinarsLearning with ReversingLabsWeekly Insights Newsletter
Customer StoriesDemo VideosDocumentationOpenSource YARA Rules
Company
About UsLeadershipCareersSeries B Investment
EventsRL at RSAC
Press ReleasesIn the News
Pricing
Software Supply Chain SecurityMalware Analysis and Threat Hunting
Request a demo
Menu
Threat ResearchJune 1, 2026

32 Red Hat npm packages backdoored in 72 seconds

RL has discovered a new supply chain attack affecting 9.8M total downloads across Red Hat's Hybrid Cloud Console JavaScript ecosystem.

ReversingLabs Inc. Logo
RL Research TeamRL Research Team
FacebookFacebookXX / TwitterLinkedInLinkedInblueskyBlueskyEmail Us
Thousands of developer projects compromised in npm hack

RL researchers have uncovered a large-scale, coordinated supply chain attack targeting the @redhat-cloud-services npm scope. On June 1, an attacker published malicious versions of 32 packages (update) in a 72-second window, injecting obfuscated preinstall malware into every one.

The affected packages collectively represent approximately 9.8 million total downloads and cover the full breadth of Red Hat's Hybrid Cloud Console JavaScript ecosystem — UI components, API clients, build tooling, configuration utilities, and MCP servers.

[ See the FAQ and IoCs ]

Scale of the attack

Package

Malicious Version

Published (UTC)

Total Downloads

@redhat-cloud-services/tsc-transform-imports

1.2.2

10:54:09

335,889

@redhat-cloud-services/types

3.6.1

10:54:09

1,281,228

@redhat-cloud-services/eslint-config-redhat-cloud-services

3.2.1

10:54:20

487,137

@redhat-cloud-services/entitlements-client

4.0.11

10:54:20

80,714

@redhat-cloud-services/frontend-components-testing

1.2.1

10:54:21

13,405

@redhat-cloud-services/javascript-clients-shared

2.0.8

10:54:26

507,613

@redhat-cloud-services/config-manager-client

5.0.4

10:54:25

12,448

@redhat-cloud-services/hcc-kessel-mcp

0.3.1

10:54:26

736

@redhat-cloud-services/frontend-components-remediations

4.9.2

10:54:26

112,034

@redhat-cloud-services/hcc-feo-mcp

0.3.1

10:54:27

1,324

@redhat-cloud-services/hcc-pf-mcp

0.6.1

10:54:27

3,415

@redhat-cloud-services/quickstarts-client

4.0.11

10:54:31

5,729

@redhat-cloud-services/chrome

2.3.1

10:54:42

56,869

@redhat-cloud-services/frontend-components-config

6.11.3

10:54:36

788,862

@redhat-cloud-services/frontend-components-config-utilities

4.11.2

10:54:36

874,609

@redhat-cloud-services/integrations-client

6.0.4

10:54:36

7,762

@redhat-cloud-services/frontend-components-translations

4.4.1

10:54:47

112,768

@redhat-cloud-services/frontend-components-notifications

6.9.2

10:54:53

701,097

@redhat-cloud-services/frontend-components-advisor-components

3.8.2

10:54:58

28,616

@redhat-cloud-services/notifications-client

6.1.4

10:54:58

24,738

@redhat-cloud-services/frontend-components

7.7.2

10:55:00

1,353,473

@redhat-cloud-services/frontend-components-utilities

7.4.1

10:54:59

1,491,890

@redhat-cloud-services/remediations-client

4.0.4

10:54:59

38,925

@redhat-cloud-services/rule-components

4.7.2

10:54:59

157,274

@redhat-cloud-services/sources-client

3.0.10

10:55:04

44,801

@redhat-cloud-services/host-inventory-client

5.0.3

10:55:09

226,677

@redhat-cloud-services/patch-client

4.0.4

10:55:09

15,442

@redhat-cloud-services/vulnerabilities-client

2.1.8

10:55:10

48,286

@redhat-cloud-services/compliance-client

4.0.3

10:55:21

11,302

@redhat-cloud-services/insights-client

4.0.4

10:55:21

31,116

@redhat-cloud-services/rbac-client

9.0.3

10:55:21

942,556

Total: 32 packages, ~9.8 million downloads

The 72-second window

The malicious versions span from 10:54:09 to 10:55:21 UTC — 72 seconds from first to last publish. This is not a human typing at a terminal; it is automated scripted publishing. The attacker prepared all 32 poisoned archives in advance and executed a single batch push.

The packages span two different GitHub source repositories — RedHatInsights/frontend-components and RedHatInsights/javascript-clients — confirming that the attacker had access to the @redhat-cloud-services npm scope credentials directly, not to any individual repository. This is a scope-level account compromise.

What changed in every package

The modification is identical across all 31 packages: exactly two files changed compared to the prior clean version.

package.json — a preinstall script entry is added, pointing execution at index.js:

json
"scripts": {
  "preinstall": "node index.js"
}

index.js — the package's main entry point is completely replaced with a malicious payload. In the clean referential versions, index.js contains the package's normal JavaScript exports. In the malicious versions, it is a single-line obfuscated dropper.

No other files are touched. The surgical precision — two files, same modification pattern, 31 packages — is another indicator of automated tooling.

The obfuscation technique: ROT-N + AES-128-GCM + obfuscator.io

Each malicious index.js follows the same outer structure — but what it conceals is a three-layer attack pipeline.

Outer wrapper:

javascript
try{eval(function(s,n){
  return s.replace(/[a-zA-Z]/g, function(c) {
    var b = c <= "Z" ? 65 : 97;
    return String.fromCharCode((c.charCodeAt(0) - b + n) % 26 + b)
  })
}([/* ~500,000 integer char codes */].map(function(c){return String.fromCharCode(c)}).join(""), /* N */))
}catch(e){console.log("wrapper:",e.message||e)}

Layer 1 — ROT-N caesar cipher. The outer call encodes ~4 MB of character codes. String.fromCharCode reconstructs a string, then the function(s,n) applies a ROT-N rotation to all alphabetic characters. The rotation value N differs per package — making each blob visually distinct while using the same decode engine. For the chrome package, N = 3.

Layer 2 — AES-128-GCM decryption (two blobs). The ROT-decoded string is an async IIFE that decrypts two encrypted blobs using Node.js's crypto.createDecipheriv("aes-128-gcm", ...):

javascript
(async()=>{try{
const _c = await import("node:crypto");
const _d = (k, i, a, c) => {
  const d = _c.createDecipheriv("aes-128-gcm", Buffer.from(k,"hex"), Buffer.from(i,"hex"), {authTagLength:16});
  d.setAuthTag(Buffer.from(a,"hex"));
  return Buffer.concat([d.update(Buffer.from(c,"hex")), d.final()])
};
const _b = _d(key_b, iv_b, tag_b, ciphertext_b);  // bun downloader
const _p = _d(key_p, iv_p, tag_p, ciphertext_p);  // main payload

GCM (Galois/Counter Mode) provides authenticated encryption: any tampering with the ciphertext causes decryption to fail, protecting the payload from modification. Keys, IVs, and auth tags are unique per package.

_b — bun runtime downloader. The first blob decrypts to JavaScript that downloads the bun runtime (v1.3.13) from github.com/oven-sh/bun/releases into a temp directory, makes it executable, and stores the path as globalThis.getBunPath. This is a legitimate binary from a legitimate source — a deliberate choice to avoid suspicious network traffic.

Layer 3 — Obfuscator.io payload (_p, 634 KB). The second blob — the actual payload — is written to a temp file and executed with bun. If bun is already present in the environment, it is used directly. Otherwise _b is eval'd first. After execution the temp file is deleted. The 634 KB payload is heavily obfuscated using the obfuscator.io toolchain (string array encoding, control flow flattening, identifier mangling).

The try/catch at every layer ensures silent execution: if any stage fails for any reason, no error surfaces in the build log.

Critically, every one of the 31 index.js files carries a unique SHA-256 hash. The attacker generated individually tailored payloads — rotation values, AES keys, IVs, auth tags, and ciphertexts all differ across packages. This defeats hash-based deduplication and means each package must be analyzed independently.

What the chrome payload does

Full decryption of the chrome package payload reveals a cloud credential stealer with worm propagation capabilities. The _p blob is a 634 KB bundled JavaScript program that performs several distinct functions when run with the bun runtime.

Credential harvesting. The payload reads and exfiltrates credentials from the developer's build environment via multiple collectors. Confirmed targets include:

Source

Environment Variables / Files

AWS

AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, profile files

Azure / ARM

ARM_TENANT_ID, ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_OIDC_TOKEN_FILE_PATH, AZURE_VAULT_NAME

Google Cloud

GOOGLE_APPLICATION_CREDENTIALS, application default credential files

HashiCorp Vault

VAULT_TOKEN, VAULT_AUTH_TOKEN

GitHub

GITHUB_TOKEN, GITHUB_REPOSITORY, GITHUB_WORKFLOW_REF

npm

~/.npmrc

SSH

~/.ssh/

CI/CD targeting. The payload checks GITHUB_REPOSITORY and GITHUB_WORKFLOW_REF to detect GitHub Actions environments. If the workflow reference matches an expected pattern, it triggers a separate, targeted exfiltration path before exiting. This allows quiet operation inside automated pipelines without leaving an unusual process running.

GitHub API exfiltration. Stolen credentials are formatted into structured reports and exfiltrated via the GitHub API. The payload contains a dedicated GitHub API client (githubFetch, githubJson) with Authorization header support. The command-and-control (C2) endpoint URL is stored encrypted under an additional layer (f4abccab2 decryptor) on top of the obfuscator.io string table, preventing static extraction.

Worm propagation. The payload contains a bQ() ROT-N function and pQ() payload generator identical in structure to the obfuscation used to encode the index.js files. This strongly suggests the payload is capable of generating new malicious package versions — using any npm credentials it steals to publish poisoned packages to additional scopes.

All 31 packages contain both _b and _p blobs — they are not specific to chrome. Decrypting _b across multiple packages confirms it carries identical bun downloader code in every case; only the AES-GCM key, IV, and authentication tag differ, making the binary blob unique while the decrypted function is the same. The _p payloads are all unique-keyed and have not been decrypted for the other 30 packages.

A structural split is visible from file sizes alone: four packages (chrome, frontend-components, frontend-components-advisor-components, sources-client) produce index.js files of ~4.05 MB, while the remaining 27 produce files of ~4.29 MB — approximately 238 KB more ciphertext in _p.

Detection: Behavioral indicators

ReversingLabs Spectra Assure's behavior analysis detects the injection through a cluster of indicators that are uniformly absent in the referential versions and uniformly present in the malicious ones:

Indicator

Description

BH13852

Executes files during installation or upon launch

BH15358

Contains byte sequence decodable to printable string

BH13525

Evaluates code dynamically

BH15183

Converts binary data to string (obfuscation)

Two additional indicators appear only in the chrome package payload:

Indicator

Description

BH16168

Connects through HTTP

BH13831

Sets a JavaScript interval (recurring execution)

The presence of HTTP connectivity and a repeating timer in the chrome payload indicates a more capable stage — one that establishes periodic callbacks, consistent with a persistent info-stealer or C2 beacon executing from the developer's environment. The chrome package, used in the Red Hat Hybrid Cloud Console shell, runs in browser-facing build environments with access to Red Hat infrastructure credentials.

Clean versions already published

By the time of analysis, legitimate maintainers had already pushed clean follow-up versions for all 32 packages (N+1 patch versions). The malicious versions have since been removed from npm. Any project that pinned to these exact versions or ran npm install in the window between publish and removal is affected.

Recommendations

  • If you ran npm install on June 1, 2026 between ~10:54 and ~10:56 UTC and any of these packages are in your dependency tree — direct or transitive — treat the build environment as compromised. Rotate all credentials, tokens, SSH keys, and secrets accessible from that environment.
  • Audit your lock files. Check package-lock.json or yarn.lock for exact version pins matching the malicious list above.
  • Block the malicious hashes in Artifactory, Nexus, or any other artifact proxy. See the indicators of compromise (IoC) table below.
  • Check transitive dependencies. Several of these packages are widely used as indirect dependencies; the total exposure is likely larger than direct installs suggest.
  • Monitor for anomalous outbound connections from build agents, particularly HTTP traffic initiated by Node.js processes during npm install.

Indicators of Compromise (IoCs)

All 32 malicious index.js hashes are unique (individually crafted payloads):

Package

Version

index.js SHA-256

chrome

2.3.1

21b6409a7b84446310daca5409ad6112ac60a1e4bef97736e53fff5f63bfdef4

compliance-client

4.0.3

5c6cb758a3447bc7e0de34406919a933f9351e90ef04ec43f3bbb401e7004e1b

config-manager-client

5.0.4

5dabf08e2655c012e478074a2cea2b0d34e286c27265a26f3846fc45e5584501

entitlements-client

4.0.11

2a446171b4b981d98b5af6c5606bd63b1570040334210b6ab0a10901b2606fe5

eslint-config-redhat-cloud-services

3.2.1

edd86c0efd776a6bd934fc7b0d4d6da2b256e147cfa83bb0c2814e81d849c427

frontend-components

7.7.2

3f8e522595f32277a0013c7ab0df3ecf336460b56e6b4be9130907f419db3b6d

frontend-components-advisor-components

3.8.2

d8d170af3de17bb9b217c52aaaffdf9395f35ef015a57ef676e406c121e5e223

frontend-components-config

6.11.3

545a1838c66e1771f58d84a17b3e1841e5eeab91a73f4ccc59c9492450a6d9c0

frontend-components-config-utilities

4.11.2

c2a60face766f69f82c972375f35f8ebaa45d6c464176974e631d9a78d6bea0a

frontend-components-notifications

6.9.2

080190bffcaafffacca1f0181fc9024aaaa21500ffdc9926fa5b689ba959965d

frontend-components-remediations

4.9.2

9b99482b75ee89f0d916f2743deeff381ea727e69c71491822477e67891841ad

frontend-components-testing

1.2.1

17c4312b50d69a6f61515edcf71cfaa8271fe2538b942128cfb639d021d042a7

frontend-components-translations

4.4.1

e5f73c888f1250a8895680801975cf177e8c690defd4a999e56f6c08ff64deb8

frontend-components-utilities

7.4.1

89f97557200bd26cc8941c9abaadac2d798a89562401016fbb2c757e3092dfdc

hcc-feo-mcp

0.3.1

c611e49ea46c91013448942c26049741b434cb5dac55fff7c376ca6a4f28580e

hcc-kessel-mcp

0.3.1

7cbace2a186cab2c652305b6e33c8eeb10d4a0ec3a0c8b795de012094fa0d845

hcc-pf-mcp

0.6.1

c178cafa2b3bcbefbbc283b5ab8fc6143e46650631f72451a44327f146a609c3

host-inventory-client

5.0.3

cffc487ee978f7bc06e3856b286940940658884847d38b619a137b8272a75980

insights-client

4.0.4

8d2a09b3727b50f3d035b58bd35b90b504d24dda73a8a24e926a010a58ba5f74

integrations-client

6.0.4

42e165602967c8e1a6fae0113a5179adbe33e18192244fe34b872db09c85e0e6

javascript-clients-shared

2.0.8

09b2301d1589416e0d5fb7a602427a9850dee6713ffa741c0efcfeb1eb4c8952

notifications-client

6.1.4

85b1ed56530bb64d925af4ca50faacd89efb1b63d615238a34adbea9f00e4754

patch-client

4.0.4

df1732f5bfec12e066be44dee02ec8a243e4868d38672c1b1d065359dd735a14

quickstarts-client

4.0.11

7b19ffc2f2bfff75989255e5e807d0f62513153de287eba9cc17003c1dcae8a8

rbac-client

9.0.3

94e8488fd033728eee6666550d5a94b0cc1f7b231d4d85d0affecb0615116722

remediations-client

4.0.4

396cac9e457ec54ff6d3f6311cb5cc1da8054d019ce3ffa1de5741506c7a4ea4

rule-components

4.7.2

1a30a9abe20bab121aaa75ed040565af14e6cdfb745609ee0e7b94a2d814fb9c

sources-client

3.0.10

f961d6897c0ec586cde633e100865b5b1d435cc7c301dbf0f41298ca5b42e17a

tsc-transform-imports

1.2.2

b390d9f708760b799ee5482e8050ce093219140627fcaec6df8812ac9abb9a9b

types

3.6.1

b86c5ae9e95bd841a595440faa3eb6317441e746f241ae8fd641ab59ed1d1966

vulnerabilities-client

2.1.8

d1999fd543085918dd542322c6455abde3c57a93b8f7ce871b8809c8bb744af7

Frequently Asked Questions (FAQ)

What happened to Red Hat's npm packages?

On June 1, 2026, an attacker published malicious versions of 32 packages in the @redhat-cloud-services npm scope within a 72-second window. Each compromised package contained an obfuscated preinstall script that silently executed a credential-stealing payload during any npm install run. The packages span Red Hat's Hybrid Cloud Console JavaScript ecosystem — UI components, API clients, build tooling, configuration utilities, and MCP servers — and collectively represent approximately 9.8 million total downloads.


Which Red Hat npm packages were compromised?

Thirty-two packages in the @redhat-cloud-services npm scope were backdoored. High-download packages in the affected set include @redhat-cloud-services/frontend-components-utilities (approximately 1.5 million total downloads), @redhat-cloud-services/frontend-components (approximately 1.35 million downloads), @redhat-cloud-services/types (approximately 1.28 million downloads), @redhat-cloud-services/rbac-client (approximately 942,000 downloads), and @redhat-cloud-services/frontend-components-config-utilities (approximately 875,000 downloads). The full list of affected packages, malicious version numbers, and SHA-256 hashes for each compromised index.js file is published in the indicators of compromise (IoCs) table in this post.


How did attackers manage to publish 32 packages in 72 seconds?

The attack was fully automated. All 32 poisoned packages were prepared in advance and deployed in a single scripted batch push between 10:54:09 and 10:55:21 UTC. Because the compromised packages span two separate GitHub source repositories — RedHatInsights/frontend-components and RedHatInsights/javascript-clients — repository-level access alone could not explain the breadth of the attack. The attacker had direct access to the @redhat-cloud-services npm scope credentials, allowing them to publish to any package in the scope without touching any individual code repository.


What is an npm scope compromise?

An npm scope is a namespace that groups related packages under a shared owner prefix — in this case, @redhat-cloud-services. A scope-level compromise means the attacker obtained the credentials controlling the entire namespace, not just a single package or repository. This gives the attacker the ability to publish malicious versions of every package in the scope simultaneously, which is precisely what occurred here. Scope-level credential theft is far more damaging than a single-package account takeover because it provides leverage across an entire ecosystem in a single operation.


What malware was injected into the Red Hat npm packages?

Each compromised package contained identical modifications to two files. The package.json was altered to add a preinstall script that executes index.js automatically during installation. The index.js itself was completely replaced with a single-line obfuscated dropper carrying a three-layer attack pipeline: an outer ROT-N Caesar cipher decodes roughly 4 MB of character codes; the decoded layer performs AES-128-GCM decryption on two encrypted blobs; the first blob downloads the bun JavaScript runtime, and the second blob is the 634 KB main payload — a cloud credential stealer with worm propagation capabilities, obfuscated with the obfuscator.io toolchain.


What credentials does the Red Hat npm malware steal?

The payload targets cloud and developer credentials from the build environment. Confirmed targets include AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, and profile files), Azure/ARM credentials (ARM_TENANT_ID, ARM_CLIENT_ID, ARM_CLIENT_SECRET), Google Cloud application default credentials, HashiCorp Vault tokens, GitHub tokens and workflow references, npm configuration files (~/.npmrc), and SSH keys (~/.ssh/). Stolen credentials are formatted into structured reports and exfiltrated via the GitHub API using a dedicated client embedded in the payload.


Does the malware specifically target CI/CD pipelines?

Yes. The payload checks the GITHUB_REPOSITORY and GITHUB_WORKFLOW_REF environment variables to detect GitHub Actions environments. When it identifies an automated pipeline context, it triggers a targeted exfiltration path before exiting — designed to operate quietly within build logs without leaving an unusual process running. The @redhat-cloud-services/chrome package, used in the Red Hat Hybrid Cloud Console shell, runs in browser-facing build environments with access to Red Hat infrastructure credentials, making it a particularly sensitive target.


Can this malware spread to other npm packages?

The payload contains a worm propagation mechanism. It includes functions — a ROT-N encoder and a payload generator — structurally identical to the obfuscation used to encode the compromised index.js files. If the malware successfully steals npm credentials from the infected build environment, it can generate new malicious package versions and publish them to additional npm scopes controlled by the victim organization. This self-replication capability means a single infected build environment could become the origin point of downstream supply chain attacks.


Why does the malware download the bun runtime instead of using Node.js?

The payload downloads the bun JavaScript runtime (version 1.3.13) from the official github.com/oven-sh/bun/releases repository into a temporary directory before executing the main credential-stealing payload. Using a legitimate binary from a legitimate source is a deliberate evasion choice: the network request to GitHub does not trigger security alerts the way a connection to an unknown command-and-control server would. If bun is already present in the environment, the download step is skipped entirely.


How does the malware avoid detection?

The attack uses four layered obfuscation techniques to resist analysis. First, each package's payload begins with a ROT-N Caesar cipher applied with a unique rotation value per package, making each blob visually distinct. Second, the decoded layer uses AES-128-GCM authenticated encryption — which prevents tampering and requires correct decryption keys to recover the payload. Third, the final payload is obfuscated using the obfuscator.io toolchain, applying string array encoding, control flow flattening, and identifier mangling. Fourth, every index.js file across all 32 packages carries a unique SHA-256 hash because each package received individually tailored AES keys, IVs, auth tags, and ciphertexts — defeating hash-based deduplication and requiring independent decryption of each package to fully characterize the attack.


How do I know if I'm affected by this attack?

You are potentially affected if you ran npm install on June 1, 2026 between approximately 10:54 and 10:56 UTC, and any of the 32 compromised packages appear in your dependency tree — either as a direct dependency or a transitive one. Check your package-lock.json or yarn.lock for exact version pins matching the malicious versions listed in the IoC table in this post. Because several of these packages are widely used as indirect dependencies, total exposure is likely larger than direct install counts suggest.


What should I do if I installed one of the compromised packages?

If you ran npm install during the attack window and any of the affected packages are in your dependency tree, treat the build environment as fully compromised. Rotate all credentials, tokens, SSH keys, and secrets accessible from that environment immediately — including AWS, Azure, Google Cloud, HashiCorp Vault, GitHub, and npm credentials. Block the malicious package hashes in Artifactory, Nexus, or any other artifact proxy using the SHA-256 values in the IoC table. Monitor build agents for anomalous outbound HTTP connections initiated by Node.js processes during npm install. Investigate any CI/CD jobs that ran in the affected window for signs of unauthorized activity.


Have the malicious packages been removed from npm?

Yes. Legitimate maintainers published clean follow-up versions for all 32 packages before the time of RL's analysis, and the malicious versions have been removed from npm. However, any project that pinned to the exact compromised versions in a lock file, or ran npm install during the window between initial publication and removal, may have executed the malware. Removal from the registry does not eliminate exposure that already occurred.


How did ReversingLabs detect this attack?

ReversingLabs Spectra Assure® detected the injected malware through behavioral indicators uniformly present in the malicious versions and uniformly absent in their clean counterparts: execution of files during installation or launch (BH13852), dynamic code evaluation (BH13525), conversion of binary data to strings as an obfuscation technique (BH15183), and the presence of byte sequences decodable to printable strings (BH15358). Two additional indicators detected in the chrome package payload — HTTP connectivity (BH16168) and a JavaScript interval for recurring execution (BH13831) — confirmed the more capable, persistent stage embedded in that package. Full IoC coverage for all 32 packages is available in Spectra Assure. Teams monitoring open-source dependencies with Spectra Assure will have detected this attack via BH13852 and BH13525 across all affected versions.

Watch this space

This attack illustrates the leverage a single scope-level credential compromise can provide: 32 packages, 9.8 million downloads, and a payload capable of self-propagation — all published in under two minutes. The individually crafted payloads across every package, the per-package AES-GCM key material, and the ROT-N variance are deliberate choices to defeat both hash-based detection and bulk analysis. That each package requires independent decryption to fully characterize is itself a structural defense the attacker built in.

ReversingLabs is continuing to monitor the @redhat-cloud-services scope and will update this post if additional affected versions or payload variants are identified. Full IoC coverage for all 32 packages is available in Spectra Assure. Teams using Spectra Assure to monitor open-source dependencies will have detected this attack via the BH13852 and BH13525 behavior indicators present across all affected versions.

Updated to reflect the correct number of packages affected, and an FAQ was added.

Join RL's free Spectra Assure Community, which helps secure open-source development.

This post was researched by RL AI agents and written by generative AI.

Keep learning

  • Get up to speed on the Agentic Development Security tools landscape in this June 18 webinar with Forrester Sr. Analyst Janet Worthington.
  • Learn why binary analysis is a must-have control in the Gartner® CISO Playbook for Commercial Software Supply Chain Security.
  • Take a deep dive on the state of software security with RL's Software Supply Chain Security Report 2026. Plus: See the the webinar discussing the findings.

Explore RL's Spectra suite: Spectra Assure for software supply chain security, Spectra Detect for scalable file analysis, Spectra Analyze for malware analysis and threat hunting, and Spectra Intelligence for reputation data and intelligence.

Tags:Threat Research

More Blog Posts

Hunting Megalodon Fossils

Researcher's Notebook: Hunting Megalodon Fossils

Analyzing C2 responses from compromised GitHub Actions linked a current threat to an earlier one, showing the value of retrohunting.

Learn More about Researcher's Notebook: Hunting Megalodon Fossils
Researcher's Notebook: Hunting Megalodon Fossils
Hackers Abuse Parental Controls To Hijack Google Accounts

Hackers Abuse Parental Controls to Hijack Google Accounts

Learn how attackers are re-casting adults as minors to bypass recovery and lock users out.

Learn More about Hackers Abuse Parental Controls to Hijack Google Accounts
Hackers Abuse Parental Controls to Hijack Google Accounts
How DirtyFrag rose from the Linux privilege escalation exploit

How Dirty Frag rose from the Copy Fail exploit

RL documented 163 samples of the Linux exploit's new variants, active malware — and developed YARA rules.

Learn More about How Dirty Frag rose from the Copy Fail exploit
How Dirty Frag rose from the Copy Fail exploit
Copy Fail Linux yara rules

Copy Fail Flaw: 5 YARA Rules for Detection

Here’s what you need to know about the Linux kernel privilege escalation — and how to use YARA rules to get on top of it.

Learn More about Copy Fail Flaw: 5 YARA Rules for Detection
Copy Fail Flaw: 5 YARA Rules for Detection

Spectra Assure Free Trial

Get your 14-day free trial of Spectra Assure for Software Supply Chain Security

Get Free TrialMore about Spectra Assure Free Trial
Blog
Events
About Us
Webinars
In the News
Careers
Demo Videos
Cybersecurity Glossary
Contact Us
reversinglabsReversingLabs: Home
Privacy PolicyCookiesImpressum
All rights reserved ReversingLabs © 2026
XX / TwitterLinkedInLinkedInFacebookFacebookInstagramInstagramYouTubeYouTubeblueskyBlueskyRSSRSS
Back to Top