mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 14:47:17 -07:00
Move Miasma npm abuse into dedicated page
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
- [Gh Actions - Artifact Poisoning](pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-artifact-poisoning.md)
|
- [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 - 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 - 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)
|
- [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)
|
- [Basic Github Information](pentesting-ci-cd/github-security/basic-github-information.md)
|
||||||
- [Gitea Security](pentesting-ci-cd/gitea-security/README.md)
|
- [Gitea Security](pentesting-ci-cd/gitea-security/README.md)
|
||||||
|
|||||||
@@ -745,42 +745,14 @@ 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).
|
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).
|
||||||
|
|
||||||
#### `binding.gyp` / node-gyp execution (`Phantom Gyp`)
|
#### npm supply-chain pivots from GitHub Actions
|
||||||
|
|
||||||
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`.
|
For `binding.gyp` / Phantom Gyp execution, wormable npm publishing with stolen CI identities, and the limits of trusted publishing provenance after workflow compromise, check:
|
||||||
|
|
||||||
Practical implications during an assessment:
|
{{#ref}}
|
||||||
|
gh-actions-npm-supply-chain-abuse.md
|
||||||
|
{{#endref}}
|
||||||
|
|
||||||
- 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` as their main intake control.
|
|
||||||
- Review release jobs that run `npm install`, `npm rebuild`, or other dependency build steps after restoring untrusted artifacts/caches, because a poisoned package can move execution to the native-build path.
|
|
||||||
|
|
||||||
#### Wormable npm publishing from CI / stolen maintainer identities
|
|
||||||
|
|
||||||
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 which packages the compromised identity or team can publish to.
|
|
||||||
3. Republish malicious versions across each writable package so downstream `npm install` executions create more credential-generation nodes.
|
|
||||||
|
|
||||||
This becomes more dangerous when the release workflow uses **trusted publishing**: if the attacker steals the GitHub Actions OIDC material from a job with `id-token: write`, the poisoned release can still receive **valid provenance** because the legitimate workflow really built it. Provenance answers _which workflow built this artifact_, not _whether the workflow/source tree was clean_.
|
|
||||||
|
|
||||||
Useful checks:
|
|
||||||
|
|
||||||
- Look for workflows that combine `id-token: write` with `npm publish`, `changesets`, or release bots and **do not require a human approval step**.
|
|
||||||
- Check whether the compromised identity can enumerate org/team package access (for example with `npm access ls-packages`) and whether package publishing bypasses 2FA.
|
|
||||||
- Add friction to the propagation loop with **staged publishing** / human 2FA approval and `minimumReleaseAge` quarantine before consuming newly published versions.
|
|
||||||
|
|
||||||
#### Repository-local AI assistant persistence
|
|
||||||
|
|
||||||
A compromised publisher or repo writer does not need to stop at install-time execution. Another persistence layer is to commit **assistant instruction/config files** into the repository so the next developer who opens the project feeds attacker-controlled instructions into local tooling. High-signal paths include:
|
|
||||||
|
|
||||||
- `.claude/settings.json`
|
|
||||||
- `.cursor/rules`
|
|
||||||
- `.gemini/`
|
|
||||||
- editor/IDE task or settings files that steer AI helpers
|
|
||||||
|
|
||||||
This is useful after CI compromise because the attacker can push those files with a stolen maintainer token, and the trigger later becomes **repository open / assistant load** instead of `npm install`. During reviews, diff for new assistant-policy files with the same suspicion level as new workflow files or build scripts.
|
|
||||||
|
|
||||||
#### Alternate exfil when outbound traffic is filtered
|
#### Alternate exfil when outbound traffic is filtered
|
||||||
|
|
||||||
@@ -995,12 +967,8 @@ An organization in GitHub is very proactive in reporting accounts to GitHub. All
|
|||||||
- [A Survey of 2024–2025 Open-Source Supply-Chain Compromises and Their Root Causes](https://words.filippo.io/compromise-survey/)
|
- [A Survey of 2024–2025 Open-Source Supply-Chain Compromises and Their Root Causes](https://words.filippo.io/compromise-survey/)
|
||||||
- [Weaponizing the Protectors: TeamPCP’s Multi-Stage Supply Chain Attack on Security Infrastructure](https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/)
|
- [Weaponizing the Protectors: TeamPCP’s Multi-Stage Supply Chain Attack on Security Infrastructure](https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/)
|
||||||
- [Mini Shai-Hulud: Frequently asked questions about the TeamPCP npm and PyPI supply chain campaign](https://www.tenable.com/blog/mini-shai-hulud-frequently-asked-questions)
|
- [Mini Shai-Hulud: Frequently asked questions about the TeamPCP npm and PyPI supply chain campaign](https://www.tenable.com/blog/mini-shai-hulud-frequently-asked-questions)
|
||||||
- [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)
|
|
||||||
- [Events that trigger workflows - GitHub Docs](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows)
|
- [Events that trigger workflows - GitHub Docs](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows)
|
||||||
- [Trusted publishing for npm packages | npm Docs](https://docs.npmjs.com/trusted-publishers/)
|
- [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/)
|
|
||||||
- [Generating provenance statements | npm Docs](https://docs.npmjs.com/generating-provenance-statements/)
|
- [Generating provenance statements | npm Docs](https://docs.npmjs.com/generating-provenance-statements/)
|
||||||
- [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}}
|
{{#include ../../../banners/hacktricks-training.md}}
|
||||||
|
|||||||
+92
@@ -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}}
|
||||||
Reference in New Issue
Block a user