Shai-Halud and the Secret Hunters: How npm Installs Turn into Intrusions

Written by
Janos Matyas
Published on
September 18, 2025

Shai-Halud and the Secret Hunters: How npm Installs Turn into Intrusions

TL;DR

A coordinated npm supply-chain campaign (self-branded Shai-Halud) trojanized popular packages to run a bundle.js payload at install time. The payload downloads a secret scanner (TruffleHog), validates discovered tokens (GitHub, npm, AWS, etc.), and repurposes them for persistence, exfiltration, or lateral movement (including planting GitHub Actions workflows). The root problem is static credentials living on disk or in CI - remove those and the attack collapses. Below: a tight forensic summary, Riptides’ operational stance, and two practical Riptides examples (GitHub + AWS).

From Install to Intrusion: How npm Packages Became Secret Hunters

In September 2025 a coordinated npm supply-chain campaign, calling itself Shai-Halud, began trojanizing popular packages - most visibly @ctrl/tinycolor - and rapidly expanded to hundreds of packages across multiple maintainers. Each infected package carried a hidden payload (bundle.js) that executed at install time, fetched a platform-specific TruffleHog binary, and immediately hunted the host for developer and CI credentials.

Payload behavior (at a glance)

  • Secret scanning - downloads TruffleHog and scans local files, repo history, and environment variables.
  • Token harvesting - probes for GITHUB_TOKEN, NPM_TOKEN, AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY, then calls provider endpoints (e.g., /-/whoami, GitHub API, instance metadata) to validate which tokens work.
  • Persistence - if GitHub tokens are valid, it can write a workflow file (e.g., shai-hulud-workflow.yml) into .github/workflows to regain access via CI.
  • Exfiltration - aggregates findings (e.g., data.json) and posts them to a hardcoded webhook; in some cases it created public repos under victims’ accounts.

Why this campaign is especially dangerous

It combines scale (popular, transitive packages) with credential validation. Once a single reusable secret is found, the attacker gains immediate foothold: unauthorized publishes, CI persistence, cloud lateral movement. Because the malicious logic runs at install time, developer laptops, CI runners, and build environments are all at risk. Supply-chain attacks like this are practically unavoidable: zero-days in dependencies will always surface, and even without them many developers don’t update packages regularly. The only realistic defense is to reduce the blast radius, which starts with removing static secrets that attackers can steal and reuse for lateral movement.

Tokens as Treasure

The Shai-Halud campaign makes one thing painfully clear: the single biggest enabler of modern supply-chain attacks is static, long-lived credentials lying around in files, environment variables, or CI pipelines. Once a trojanized package can read a filesystem, a build cache, or a CI runtime, an attacker doesn’t need to exploit anything else - they already have a “door key” into your systems.

At Riptides, we frame this as a supply-chain symmetry problem: attackers only need one reusable secret to start lateral movement and persistence; defenders have to eliminate every reusable secret. That’s why we advocate a hard operational rule: never store long-lived or static credentials on disk, in repositories, or in CI configurations.

The problem isn’t just that secrets are lying around. Modern supply-chain malware is smart enough to validate credentials in real time. TruffleHog, used by Shai-Halud, doesn’t just harvest keys; it checks whether they work. GitHub tokens are tested against the API, AWS keys are checked via instance metadata or STS calls. If the token works, it’s immediately leveraged: the malware can write GitHub Actions workflows, publish malicious packages, or assume cloud roles. This transforms a local compromise into account-wide or even cross-account access - and all it took was a secret sitting in a file.

Static credentials aren’t just dangerous - they’re high-value targets. Every credential that persists beyond a single, scoped operation is a potential beachhead. Developer machines, CI runners, build agents - all of these environments are full of sensitive tokens and metadata. One compromised node, one scanned file, and an attacker has an actionable key in hand. Once that happens, lateral movement is almost inevitable.

At Riptides, our philosophy is simple: move identity off disk, limit its lifetime, and bind it to the workload that needs it. We issue ephemeral tokens via OIDC or SPIFFE-backed flows and anchor non-human identity at the kernel level. Tokens are injected on-the-wire for network requests and never exposed on disk or in environment variables. Even if malware runs in the same node, it sees nothing it can reuse. Dependencies introduced via supply chain attacks operate strictly in user-space, where they cannot access credentials protected by Riptides; as Riptides injects ephemeral credentials directly in kernel-space, malicious packages are unable to intercept or exfiltrate secrets, even if running on the same compromised node. This architectural boundary ensures that credential theft by supply chain malware is fundamentally blocked at the OS level.

This approach changes the calculus for attackers. A stolen file becomes noise, not a beachhead. Replayed tokens expire quickly or are scoped to a workload that the attacker cannot control. By minimizing persistence and enforcing strict least privilege, the supply chain becomes far less fertile ground for exploitation.

In short: static secrets are the Achilles’ heel of the software supply chain. Remove them, and the attack surface shrinks dramatically. At Riptides, we replace them with ephemeral, verifiable credentials, injected on the wire, ensuring that stolen files and environment dumps are useless to attackers.

Two examples from the current Shai-Halud exploit

Example A - GitHub: install → secrets hunt

Typical exploit start
bundle.js runs during npm install, scans the filesystem and environment for GitHub tokens. Valid tokens are immediately reused to push workflows, publish packages, or exfiltrate secrets.

Riptides options for workloads that need GitHub access

  1. Static-but-isolated token (sysfs injection)
    • The workload receives a static token but it is never written to disk. The kernel exposes it via a kernel-backed sysfs object readable only by that process; the kernel injects the token onto the wire when the process talks to GitHub.
    • Why it helps: a postinstall script or malicious process in node_modules cannot read that sysfs object and so cannot steal the token.
  2. Short-lived GH token (recommended)
    • The workload is associated with a Secret Source and a GitHub Service in Riptides. Riptides mints ephemeral GitHub tokens on demand and injects them into outgoing requests at the kernel layer. Tokens never appear in process files, logs, or CI config; they are short TTL and rotated automatically.
    • Why it helps: even if the payload finds strings that look like tokens, those tokens are stale; live tokens exist only in-flight and only for tightly scoped operations.

Takeaway: Move GitHub credentials off disk, prefer kernel injection and short TTLs.

Example B - AWS access: secretless, on-the-wire access

Attack scenario
bundle.js searches for AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. Valid keys let an attacker enumerate roles, list S3, create keys, assume roles, or spin up resources, and enabling cloud lateral movement.

Riptides secretless flow (on-the-wire SigV4 signing)

  1. Riptides is registered as an OIDC IdP / trusted issuer in the AWS account and roles are created that accept Riptides-issued ID tokens.
  2. A CredentialSource / WorkloadCredential declares which role a workload can assume and the allowed scope/TTL.
  3. When the workload makes an AWS API request, the kernel interposes: Riptides mints short-lived STS credentials, performs SigV4 signing (or injects credentials into the wire), and the request leaves the host already signed - the client process never sees raw keys.

Why this breaks the exploit

  • No persistent keys to find on disk or in environment variables.
  • Temporary creds are short TTL, narrowly scoped, and bound to the workload context.
  • Kernel-anchored identity prevents trivial replay or cross-process misuse.

Takeaway: Sign and inject AWS credentials on the wire; never bake keys into clients, images, or CI.

You can read more about credential injection and federation done with Riptides in the following posts:

Closing - why this matters and what to do next

Shai-Halud is a clear reminder: the weakest link in a software supply chain is often a credential sitting on disk. The most effective defense isn’t another scanner, it’s changing where identity lives. Move credentials off disk, mint them just-in-time, scope them tightly, and keep them in memory or injected on the wire by an authority that can be audited and controlled.

At Riptides, we’re strong believers in SPIFFE-based workload identities, enabling fine-grained, zero-touch authentication with secure, ephemeral credentials and no secrets ever stored. This is the most robust and future-proof way to handle non-human identities, and it works seamlessly across multi-cloud environments.

But where SPIFFE adoption isn’t possible, Riptides provides a fallback: on-the-wire credential injection, delivering the right cloud or service credentials directly into the request stream without ever touching the application.

On-the-wire credential injection with Riptides enables secure, secretless invocation of external services. In this example, we demonstrated the approach with an AWS Bedrock agent, but Riptides provides the same seamless support across all major cloud providers - AWS, GCP, and Azure.

Beyond cloud credentials, Riptides can also inject OAuth2 tokens, whether sourced from Kubernetes secrets or obtained via OAuth2 authorization code flows, directly into client requests.

This pattern can be extended to agents, applications, and services in any environment, offering a unified, secure approach for managing non-human identities at scale.

If you enjoyed this post, follow us on LinkedIn and X for more updates. If you’d like to see Riptides in action, get in touch with us for a demo.

Share this post
supply-chain

Ready to replace secrets
with trusted identities?

Build with trust at the core.