# Install hooks harvest credentials

Install/build-time code reading env, tokens or memory and sending them out

_Area: Software supply chain and CI/CD. Seen in 15 disclosed reports; one confirmed bounty: $1,500; latest 2026-09-30. Updated 2026-10-23._

## How it works
Installing or building a dependency runs code with the developer's or CI runner's full environment. The broken assumption is that installing a package is passive: that only the declared entry point runs, and only when imported. In practice the package manager or build tool executes code at install or build time (preinstall/postinstall, node-gyp rebuild, gyp `conditions` evaluated as Python, plugin lifecycle hooks). That code inherits env vars, cloud/CI tokens, npm tokens, and can read process memory, then exfiltrate. Because it runs before any application logic, review of the package's main entry never sees it [E1](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md)[E2](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared.md)[E5](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-shai-hulud-2-0-ongoing-supply-chain-attack.md).

## Where it shows up
- preinstall/postinstall/setup scripts, or a `binding.gyp` whose `conditions`/`<!(...)` run shell or Python at install [E1](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md)[E8](https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-popular-code-generator-for-tanstack-query-hit-by-supply-chain-worm.md)
- Lifecycle hooks that run without install scripts: module-scope logger init, gateway startup, memory recall [E6](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-sckit-supply-chain-worm-hits-memtensor-npm-pypi-scopes.md)
- New files or size jumps versus a prior clean version (272KB to 43.6MB) [E6](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-sckit-supply-chain-worm-hits-memtensor-npm-pypi-scopes.md)
- `example/` and `test/` build files (build.gradle.kts, project.pbxproj) shipped in the tarball [E7](https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-compromised-flutter-package-on-pub-dev-contains-xcsset-malware.md)
- Phantom dependencies absent from package.json; dropper deletes setup.js and swaps in a clean stub [E4](https://bugbountylibrary.com/r/blog%3Ahuntress-com-blog-supply-chain-compromise-axios-npm-package.md)
- Repo-level (not branch/workflow) OIDC trusted publishing; tokens with write plus bypass_2fa [E2](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared.md)[E3](https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-shai-hulud-chaindrop-npm-supply-chain.md)

## How to review
Establish the invariant: no code executes at install or build time that reads secrets or reaches the network. Concretely: diff the published tarball/wheel against the sdist and prior version; enumerate every file the build tool will execute; confirm no lifecycle script, gyp substitution or Python condition, or auto-run hook exists. For CI, verify publish tokens are scoped to branch/workflow, not repo-wide, and that no long-lived NPM_TOKEN overrides OIDC [E4](https://bugbountylibrary.com/r/blog%3Ahuntress-com-blog-supply-chain-compromise-axios-npm-package.md). Run suspicious packages in an isolated runner in audit mode and inspect the process tree for unexpected children (curl, unzip, bun, python reading /proc memory) [E1](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md)[E2](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared.md).

## Variants seen
- 157-byte binding.gyp abusing gyp command substitution, bypassing script scanners [E1](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md)
- binding.gyp `conditions` evaluated as Python by node-gyp, no preinstall needed [E8](https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-popular-code-generator-for-tanstack-query-hit-by-supply-chain-worm.md)
- preinstall hook downloading Bun to run an obfuscated stealer [E2](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared.md)[E3](https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-shai-hulud-chaindrop-npm-supply-chain.md)[E5](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-shai-hulud-2-0-ongoing-supply-chain-attack.md)
- Phantom dependency with postinstall dropper delivering a RAT [E4](https://bugbountylibrary.com/r/blog%3Ahuntress-com-blog-supply-chain-compromise-axios-npm-package.md)
- Bundled Go binary launched from plugin lifecycle hooks [E6](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-sckit-supply-chain-worm-hits-memtensor-npm-pypi-scopes.md)
- Infected maintainer machine injecting build hooks into example/ files [E7](https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-compromised-flutter-package-on-pub-dev-contains-xcsset-malware.md)

## Why fixes fail
Removing preinstall/postinstall scanning is insufficient: gyp substitution [E1](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md), gyp Python conditions [E8](https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-popular-code-generator-for-tanstack-query-hit-by-supply-chain-worm.md), and lifecycle hooks [E6](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-sckit-supply-chain-worm-hits-memtensor-npm-pypi-scopes.md) execute without those scripts. Droppers delete setup.js and replace package.json with a clean stub, so the phantom dependency directory, not the manifest, is the durable indicator [E4](https://bugbountylibrary.com/r/blog%3Ahuntress-com-blog-supply-chain-compromise-axios-npm-package.md).

## Impact and severity
High: cloud/CI credentials and npm tokens stolen, enabling self-propagation across hundreds of packages and 25K+ repos [E1](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md)[E3](https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-shai-hulud-chaindrop-npm-supply-chain.md)[E5](https://bugbountylibrary.com/r/blog%3Awiz-io-blog-shai-hulud-2-0-ongoing-supply-chain-attack.md). Severity rises with repo-wide publish trust [E2](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared.md), long-lived tokens overriding OIDC [E4](https://bugbountylibrary.com/r/blog%3Ahuntress-com-blog-supply-chain-compromise-axios-npm-package.md), and shared runner UID allowing /proc memory reads [E1](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md)[E2](https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared.md).

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-binding-gyp-npm-supply-chain-attack-spreads-like-worm.md
- E2: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-a-mini-shai-hulud-has-appeared.md
- E3: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-shai-hulud-chaindrop-npm-supply-chain.md
- E4: https://bugbountylibrary.com/r/blog%3Ahuntress-com-blog-supply-chain-compromise-axios-npm-package.md
- E5: https://bugbountylibrary.com/r/blog%3Awiz-io-blog-shai-hulud-2-0-ongoing-supply-chain-attack.md
- E6: https://bugbountylibrary.com/r/blog%3Astepsecurity-io-blog-sckit-supply-chain-worm-hits-memtensor-npm-pypi-scopes.md
- E7: https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-compromised-flutter-package-on-pub-dev-contains-xcsset-malware.md
- E8: https://bugbountylibrary.com/r/blog%3Aaikido-dev-blog-popular-code-generator-for-tanstack-query-hit-by-supply-chain-worm.md
