CI installs dependencies without running the code they ship
A dependency that runs code during install gets a shell on the runner, with whatever token the job holds and whatever the job can push to. That is the step the September 2025 npm worm used to spread, and it needs no vulnerability in the project: installing is enough. Every package manager that has this problem has now shipped a control for it, so the rule is about writing the control down where a reader can see it rather than inheriting whatever the runner’s manager version happens to default to.
Observable check
every CI step that installs registry dependencies either runs the package manager in a mode that executes no dependency-supplied install or build code, or the repository commits the allowlist that manager reads. For the npm ecosystem that is --ignore-scripts on the install command, or allowScripts in package.json for npm 12, enableScripts: false for Yarn, allowBuilds for pnpm, or trustedDependencies for Bun. For Composer it is --no-scripts and --no-plugins, or the allow-plugins map in composer.json, which from Composer 2.2.0 permits nothing until a plugin is listed. For Python it is --only-binary, because a wheel install runs no packaged code where a source distribution runs the project's build backend. Where the package manager documents no way to decline that code, the rule falls outside that ecosystem rather than failing it: that is Cargo, whose build.rs runs for every dependency that has one and can only be replaced through the links override; RubyGems, whose native extensions build on install; Hex, which compiles dependency source; Maven and NuGet, which run only what the project's own build file declares; and Go modules, container images, and pub.dev packages, where nothing a dependency ships runs during resolution at all.
Where this comes from
- https://github.com/npm/cli/releases/tag/v12.0.0
- https://github.com/npm/cli/blob/latest/docs/lib/content/commands/npm-install-scripts.md
- https://yarnpkg.com/configuration/yarnrc
- https://pnpm.io/supply-chain-security
- https://bun.com/docs/pm/cli/install
- https://getcomposer.org/doc/06-config.md
- https://pip.pypa.io/en/stable/cli/pip_install/
Last read against these sources on 2026-08-03.
The falls-outside list was read once per ecosystem rather than assumed. Cargo documents no way to decline a dependency build.rs beyond the links override, RubyGems builds native extensions on install with no documented allowlist, Mix documents no flag that compiles a project without compiling its dependencies, Maven and NuGet execute only what the consuming project own build file declares, and Go modules, pub.dev packages, and container base images run nothing during resolution. The rule asks for the flag or the allowlist to be written down even where the manager now blocks this code by default, which is this project position and the same one R-SEC-08 takes about frozen installs: a default that depends on the runner manager version is not evidence in a configuration file. What would retire that half is every manager in scope making the control unconditional.