Several do. npm, Yarn and pnpm can run lifecycle scripts from dependencies. pip can run code when it builds a source distribution. Cargo compiles and runs build scripts. RubyGems builds native extensions at install. Composer is different: it runs only the root project's scripts.
What each documentation says
| Ecosystem | Code that can run at install or build | Source of the claim |
|---|---|---|
| npm | preinstall, install, postinstall, prepare, plus implicit node-gyp rebuild | npm scripts docs |
| pnpm | Dependency build scripts, but only after approval | pnpm build settings |
| Bun | Scripts only for trusted packages | Bun lifecycle docs |
| pip | Code from distributions it installs, including source builds | pip secure installs docs |
| Cargo | A package's build script runs just before that package is built | Cargo build script docs |
| RubyGems | Native extensions built at install time | RubyGems guide |
| Composer | Only scripts in the root composer.json run | Composer scripts docs |
Why the differences matter
A malicious package wants to run once, early, and quietly. Anything in the table that executes without a human reading it is a candidate.
Defaults differ. Bun and pnpm lean toward approval first. npm leaves scripts on unless you turn them off. Composer runs only the root project's scripts, though its plugin system is a separate mechanism that the same page lists.
Build-time execution counts too. Cargo's documentation says Cargo compiles a build script and then runs it just before building a package, and dependencies are packages. So a compromised crate's build script can run on your build machine.
What to do with this table
- List the ecosystems your teams use. Many shops use three or four.
- For each one, find the switch that limits install-time code, or the approval step.
- Build in a clean container or CI runner with no long-lived secrets, so a script that does run has little to steal.
- Keep an inventory of what you install, so you can answer which projects pulled a bad package.
Click through it at your own pace, or open it full screen. Look for how many ecosystems appear in one inventory.
Quick check
Does using a lockfile stop install-time code?
No. A lockfile pins versions. It does not stop a pinned package from running its script. It does stop a surprise new version from arriving.
Is pip safer if I only use wheels?
The pip documentation pairs hash checking with disallowing source distributions. Wheels avoid building from source, but you still import and run the package later.
Safeguard does SBOM and dependency scanning across ecosystems. A free scan shows what you have installed.
Sources
- npm scripts
- pnpm build settings
- Bun lifecycle scripts
- pip secure installs
- Cargo build scripts
- RubyGems: gems with extensions
- Composer scripts
Last reviewed: 19 October 2026.