You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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).
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`.
751
+
752
+
Practical implications during an assessment:
753
+
754
+
- 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.
755
+
- 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.
756
+
- 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.
757
+
758
+
#### Wormable npm publishing from CI / stolen maintainer identities
759
+
760
+
Once code runs in a maintainer workstation or release workflow, a single stolen registry identity can be turned into **self-propagating package compromise**:
2. Enumerate which packages the compromised identity or team can publish to.
764
+
3. Republish malicious versions across each writable package so downstream `npm install` executions create more credential-generation nodes.
765
+
766
+
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_.
767
+
768
+
Useful checks:
769
+
770
+
- Look for workflows that combine `id-token: write` with `npm publish`, `changesets`, or release bots and **do not require a human approval step**.
771
+
- Check whether the compromised identity can enumerate org/team package access (for example with `npm access ls-packages`) and whether package publishing bypasses 2FA.
772
+
- Add friction to the propagation loop with **staged publishing** / human 2FA approval and `minimumReleaseAge` quarantine before consuming newly published versions.
773
+
774
+
#### Repository-local AI assistant persistence
775
+
776
+
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:
777
+
778
+
- `.claude/settings.json`
779
+
- `.cursor/rules`
780
+
- `.gemini/`
781
+
- editor/IDE task or settings files that steer AI helpers
782
+
783
+
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.
784
+
748
785
#### Alternate exfil when outbound traffic is filtered
749
786
750
787
If direct exfiltration is blocked but the workflow still has a write-capable `GITHUB_TOKEN`, the runner can abuse GitHub itself as the transport:
@@ -958,8 +995,12 @@ An organization in GitHub is very proactive in reporting accounts to GitHub. All
958
995
- [A Survey of 2024–2025 Open-Source Supply-Chain Compromises and Their Root Causes](https://words.filippo.io/compromise-survey/)
959
996
- [Weaponizing the Protectors: TeamPCP’s Multi-Stage Supply Chain Attack on Security Infrastructure](https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/)
960
997
- [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)
998
+
- [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)
961
999
- [Events that trigger workflows - GitHub Docs](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows)
962
1000
- [Trusted publishing for npm packages | npm Docs](https://docs.npmjs.com/trusted-publishers/)
1001
+
- [Staged publishing for npm packages | npm Docs](https://docs.npmjs.com/staged-publishing/)
0 commit comments