Install scripts

Check C16 · execution surface family · severity MEDIUM · automatic · one of the 22 checks

The question this check asks: does this repository carry a script that the package manager will run, as you, the moment you install it — before you have read a line of what it does?

Why it matters

Installing is running. Python's pip install . executes setup.py with your privileges by design — PEP 517 makes that the build interface, not a bug — and Python has no switch to turn it off. The JavaScript ecosystem spent a decade learning the same lesson through postinstall hooks until npm v12, in June 2026, turned lifecycle scripts off by default; pnpm 10 and later, Bun and Yarn PnP had already blocked them. The reason those defaults changed is that an install script is the cheapest place in a repository to put a payload: it runs once, on every machine that installs, and nobody reads it because it is boilerplate.

The repository vetting standard's rule is short: never install with lifecycle scripts enabled; prefer wheels or a container. This check exists to tell you, before the download, that the rule applies here.

How RepoGates scores it

C16 reads the repository's file list — one API call, no clone, no file contents — and fires when setup.py sits at the root. The finding is MEDIUM, costs 5 points, and reads “arbitrary python on pip install .”. A repository that trips nothing else scores 95, the badge stays green, and the verdict is REVIEW: the download is held, the finding is shown, and proceeding is one click, recorded. It never blocks on its own. It belongs to the execution-surface family, whose evidence note in the scoring table explains the light weight for the whole group:

“28.8% of top-100 repos carry devcontainers — informative, not damning”

Execution-surface findings are things legitimate projects do all the time. They are scored to be seen, not to be feared; the default personal policy warns on every one of them and blocks only on the two with a near-zero measured false-positive cost — a nested bare repository and hidden Unicode in an agent rules file.

False positives we know about

Most of the Python ecosystem written before 2022 fires this check. A setup.py that contains nothing but a package name and a version looks, from the file list, identical to one that downloads a payload — the check sees the file, not what is in it — so it cannot be more than a warning. What the board does is name the file, so that when you do install you do it the way the standard says: wheels only, scripts off, or inside a container. A deep scan reads the file itself and replaces the verdict with what it found.

What this check does not cover

It reads the file list, so it sees only what is named there. A package.json with a postinstall hook, a Makefile, an install.sh the README tells you to run — none of those fire C16, because telling them apart from harmless files of the same name needs their contents. Nor does the check see anything that runs only because you ran it. The related checks below cover the files that run without you: a devcontainer on folder open, an editor task on workspace trust, a Rust build script when the language server starts.

And RepoGates as a whole gates browser downloads only — it does not see git clone, package managers, curl, or fetches made by AI agents outside the browser. It does not see pip install itself; it sees the file that pip will run, before the download that puts it on your machine.

Check it yourself

Without installing anything: look at the root of the repository for setup.py, package.json (and open it for a scripts block with preinstall or postinstall), Makefile, or any install.sh. With the GitHub CLI:

gh api repos/OWNER/REPO/git/trees/HEAD?recursive=1 --jq '.tree[].path' | grep -E '^(setup\.py|package\.json|Makefile|install\.sh)$'

Then install the way the standard says, whatever you found:

pip install --only-binary=:all: PACKAGE
npm install --ignore-scripts

If a project cannot be installed without its script, install it in a container, and read the script first — it is usually short.

Questions

Does every Python project fire this check? Many older ones do — setup.py was the standard for years, and most of them are harmless. That is why the check is a warning worth 5 points, never a block: the finding tells you the file is there so you install with the scripts disabled or in a container, and the decision is yours. Projects built on pyproject.toml alone do not fire it.

Does a warning stop the download? It holds it. The decision page lists the findings — here, that setup.py runs arbitrary Python on pip install — and proceeding is one click, recorded on your machine. A block is reserved for findings with a measured near-zero false-positive cost, and this is not one of them.

Does RepoGates stop git clone? No. RepoGates gates browser-initiated downloads — Download ZIP and release-asset archives. It does not see git clone, package managers, curl, or fetches made by AI agents outside the browser — and it does not see pip install itself, only the file that pip will run.

Related checks

C10 Devcontainer auto-execution — a command that runs on the host when the folder opens; one of the two execution-surface findings graded critical · C14 Build scripts and wrapper JARsbuild.rs, Gradle and Maven wrappers, CMake · C17 Directory-entry hooks — an .envrc that runs on cd.

Add RepoGates to Chrome Pricing

Numbers on this page: Phase 0 controls of 2026-08-14 (80 popular repositories); npm v12 default change, June 2026; weights from the product's scoring table. Check numbering follows the product's catalogue.