Merge pull request #312 from HackTricks-wiki/update_What_the_Miasma_Campaign_Reveals_About_the_New_S_9de20d9245b07fa3

What the Miasma Campaign Reveals About the New Supply Chain ...
This commit is contained in:
SirBroccoli
2026-06-25 18:06:10 +02:00
committed by GitHub
3 changed files with 102 additions and 0 deletions
+1
View File
@@ -17,6 +17,7 @@
- [Gh Actions - Artifact Poisoning](pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-artifact-poisoning.md)
- [GH Actions - Cache Poisoning](pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-cache-poisoning.md)
- [Gh Actions - Context Script Injections](pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-context-script-injections.md)
- [GH Actions - npm Supply Chain Abuse](pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md)
- [Accessible Deleted Data in Github](pentesting-ci-cd/github-security/accessible-deleted-data-in-github.md)
- [Basic Github Information](pentesting-ci-cd/github-security/basic-github-information.md)
- [Gitea Security](pentesting-ci-cd/gitea-security/README.md)
@@ -745,6 +745,15 @@ import base64,os;exec(base64.b64decode(os.environ["STAGE2_B64"]))
Drop the line above into a file such as `evil.pth` inside `site-packages` and it will execute during Python startup. This is especially useful in build agents that continuously spawn Python tooling (`pip`, linters, test runners, release scripts).
#### npm supply-chain pivots from GitHub Actions
For `binding.gyp` / Phantom Gyp execution, wormable npm publishing with stolen CI identities, and the limits of trusted publishing provenance after workflow compromise, check:
{{#ref}}
gh-actions-npm-supply-chain-abuse.md
{{#endref}}
#### Alternate exfil when outbound traffic is filtered
If direct exfiltration is blocked but the workflow still has a write-capable `GITHUB_TOKEN`, the runner can abuse GitHub itself as the transport:
@@ -0,0 +1,92 @@
# GH Actions - npm Supply Chain Abuse
{{#include ../../../banners/hacktricks-training.md}}
## Overview
After an attacker gets code execution in a GitHub Actions release workflow, maintainer workstation, or package build pipeline, npm publishing becomes a high-impact pivot. The goal is usually to steal publisher identity material, publish malicious versions, and turn downstream installs into more credential-generation nodes.
Typical credential sources:
- `~/.npmrc`, `NPM_TOKEN`, registry sessions, and npm automation tokens.
- GitHub PATs, `GITHUB_TOKEN`, release-bot credentials, SSH keys, and `.netrc` / git credential helpers.
- GitHub Actions OIDC request material (`ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN`) in jobs with `id-token: write`.
- Cloud credentials, Vault tokens, Kubernetes service account tokens, and `.env` files present in the release environment.
## Install-Time Execution Primitives
### Lifecycle hooks
The classic npm route is to publish a malicious package version with `preinstall`, `install`, `postinstall`, or `prepare` scripts. Any developer workstation or CI job that installs the version executes attacker-controlled code.
```json
{
"scripts": {
"postinstall": "node ./scripts/collect.js"
}
}
```
Defenders often monitor these scripts, so red-team reviews should also inspect less obvious execution paths.
### `binding.gyp` / node-gyp execution (Phantom Gyp)
Not every install-time execution path lives in `package.json` lifecycle hooks. `node-gyp`'s configure step looks for a `binding.gyp` file in the package directory, so a compromised publisher can shift execution into the native build path and bypass controls that only audit `preinstall` / `postinstall`.
Practical checks:
- Inspect the **published tarball**, not only the Git repo, for unexpected `binding.gyp`, `node-gyp`, or native-addon metadata in packages that should be pure JavaScript.
- Treat a sudden `binding.gyp` addition as an execution primitive, especially if defenders rely on lifecycle-hook monitoring or `--ignore-scripts`.
- Review release jobs that run `npm install`, `npm rebuild`, or dependency build steps after restoring untrusted artifacts/caches.
## 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. Harvest maintainer secrets (`~/.npmrc`, PATs, OIDC request env vars, cloud creds, SSH keys).
2. Enumerate packages the compromised identity or team can publish to.
3. Republish malicious versions across each writable package.
4. Let downstream installs create more credential-generation nodes.
Useful enumeration from a compromised npm identity:
```bash
npm whoami
npm access ls-packages
npm access ls-collaborators <scope-or-package>
```
Attackers usually prefer packages with frequent CI installs, transitive popularity, or release automation that will install the malicious version quickly.
## 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.
Provenance answers **which workflow built this artifact**, not **whether the workflow, source tree, cache, or build steps were clean**.
High-signal review points:
- Workflows combining `id-token: write` with `npm publish`, `pnpm publish`, `changesets`, release bots, or custom publish wrappers.
- Release jobs that restore caches or artifacts from lower-trust workflows before publishing.
- Jobs that publish without human approval, environment protection rules, or a second reviewer.
- Workflows that request OIDC before all build inputs have been verified.
## Hardening
- Use trusted publishing/OIDC instead of static npm tokens, but pair it with protected environments and human approval for sensitive scopes.
- Add staged publishing / human 2FA approval for high-impact packages where possible.
- Use `minimumReleaseAge` or equivalent dependency quarantine controls before consuming newly published package versions.
- Separate cache keys by trust boundary and never execute restored cache contents before integrity checks.
- Diff published tarballs against source repositories, and alert on unexpected native build metadata such as `binding.gyp`.
- Disable or tightly review lifecycle scripts in CI (`npm config set ignore-scripts true`) where builds do not need them.
- Monitor package access (`npm access ls-packages`) and remove stale maintainers, bots, and teams.
## References
- [What the Miasma campaign reveals about the new supply chain threat model and the underground market for developer credentials](https://www.tenable.com/blog/what-the-miasma-campaign-reveals-about-the-new-supply-chain-threat-model-and-the-underground)
- [Trusted publishing for npm packages | npm Docs](https://docs.npmjs.com/trusted-publishers/)
- [Staged publishing for npm packages | npm Docs](https://docs.npmjs.com/staged-publishing/)
- [npm orgs | npm Docs](https://docs.npmjs.com/using-npm/orgs.html)
- [node-gyp README](https://github.com/nodejs/node-gyp)
{{#include ../../../banners/hacktricks-training.md}}