On a routine Thursday, packages under the @redhat-cloud-services namespace on npm began executing malware during installation. The compromised packages—including @redhat-cloud-services/types—ran malicious code through npm lifecycle scripts, turning trusted dependencies into credential harvesters.
This wasn't a typosquatting attack or a look-alike package. The actual Red Hat namespace was compromised, and packages that passed your initial security review months ago became attack vectors overnight.
Timeline
The attack unfolded as part of the broader "Miasma" campaign, following patterns seen in recent supply chain compromises:
Initial compromise: Attackers gained access to publish rights for packages in the @redhat-cloud-services namespace. The exact entry point remains unclear.
Payload deployment: Malicious versions were published with install-time scripts embedded in the package lifecycle hooks. When developers ran npm install or CI/CD pipelines pulled updates, the scripts executed automatically.
Second-stage activation: The install script acted as a downloader, fetching additional payloads designed to steal credentials, harvest environment variables, and propagate through connected systems.
Detection: Sonatype's automated monitoring flagged the anomalous behavior, triggering investigation and public disclosure.
Which Controls Failed
Namespace trust assumption: Most dependency scanning tools flag new or unknown packages but give established namespaces like @redhat-cloud-services a pass. Your allowlist probably included this namespace based on Red Hat's reputation, not continuous verification of each published version.
Lifecycle script oversight: npm lifecycle scripts (preinstall, postinstall) execute with the same permissions as your build process. If you're not explicitly auditing these hooks before installation, you're running arbitrary code from the internet with production credentials.
CI/CD credential exposure: The second-stage payload specifically targeted CI/CD environments, where AWS credentials, npm tokens, and Git access keys often live as environment variables. Once the malware executed in your pipeline, it had access to everything your build process could touch.
Version pinning gaps: Teams that used version ranges (^1.0.0) or latest tags automatically pulled malicious updates. Even teams with lockfiles were vulnerable if they ran npm update or let Dependabot merge updates without manual review.
What Standards Require
NIST 800-53 Rev 5 SA-10 (Developer Configuration Management) requires organizations to "employ integrity verification tools to detect unauthorized changes to software." Your dependency management process needs continuous integrity checks, not just initial vetting.
ISO/IEC 27001:2022 Annex A.8.31 (Separation of Development, Testing, and Production Environments) mandates that development tools and dependencies should not have direct access to production credentials. If your CI/CD pipeline runs with production AWS keys, a compromised package becomes a production breach.
SOC 2 Type II CC6.8 (Logical and Physical Access Controls) requires that "the entity restricts the transmission, movement, and removal of information to authorized internal and external users." Environment variables in CI/CD are "information in motion"—they need the same protection as data at rest.
PCI DSS v4.0.1 Requirement 6.3.2 states that "software engineering techniques or other methods are defined and in use to prevent or mitigate common software attacks and related vulnerabilities in bespoke and custom software." Lifecycle script auditing falls under this requirement—you're responsible for code that runs in your environment, even if it came from npm.
Lessons and Action Items
Implement pre-install script auditing: Before any package installs in your environment, extract and review its lifecycle scripts. Tools like npm-audit-ci can block installations that contain preinstall or postinstall hooks until you've manually approved them. Add this check to your CI/CD pipeline before npm install runs:
# Fail if any new package contains install scripts
npm ls --json | jq '.dependencies | to_entries[] | select(.value.scripts.preinstall or .value.scripts.postinstall)'
Separate credential scopes by environment: Your CI/CD pipeline doesn't need production AWS credentials to run tests or build artifacts. Create separate IAM roles with minimal permissions for each pipeline stage. If a compromised package steals your CI credentials, it should only access dev resources.
Pin exact versions and audit updates: Replace version ranges with exact versions in package.json. When Dependabot or Renovate suggests an update, treat it like a pull request from an external contributor—review the diff, check the changelog, and look for unexpected changes in package size or dependency tree.
Monitor package behavior at runtime: Deploy runtime monitoring that detects when a Node process makes network requests to unexpected domains or reads credential files. Tools like falco or custom eBPF probes can alert when npm packages behave differently than their historical baseline.
Build a package reputation database: Don't rely on namespace reputation alone. Track each package's behavior over time: Does it normally make network requests? Does it access the filesystem? When a trusted package suddenly starts downloading executables or reading ~/.aws/credentials, that's your signal.
Audit your allowlists: If you maintain an approved package list, add a "last verified" timestamp to each entry. Packages older than 90 days without re-verification should trigger a review, regardless of namespace reputation.
The Red Hat compromise proves that "trusted" is a temporary state, not a permanent attribute. Your dependency management strategy needs to account for packages that turn malicious mid-lifecycle—because that's not a theoretical risk anymore.



