◉ANTIGRAVITY LABJP
Articles/App Development
▣ App Development/2026-07-15Advanced

Quarantining the Dependencies Your Agent Adds, Before They Install

When an agent adds a dependency overnight, nobody reviews the lifecycle scripts that run at install time. Here is how I turned the default off and built a quarantine score to let the safe ones through.

Antigravity386npm5supply chainpostinstallunattended runs6

✦ Premium Article

The tasks I had queued for the agent overnight were done by morning. Tests passing. Scrolling through the diff, I noticed one new line in package.json: a small library for parsing CLI arguments. Four-digit weekly downloads. Published eleven days ago.

Nothing was wrong with it functionally. But the moment that dependency unpacked into node_modules, a postinstall script had run once on my machine. The agent had done exactly the job it was given — make the tests pass. Reading that script was a job nobody had been assigned.

As an indie developer running several apps alongside a set of Stripe-billed sites, the only thing that quietly grows is the number of times a dependency decision gets made. The same machine also builds what I ship to the App Store. That is why one added line bothered me.

npm install is not a download. It is an execution. Back when I added dependencies by hand, there was a beat before I typed that line — enough to glance at the name, maybe search it. Hand the work to an agent and that beat disappears.

What npm install Actually Runs

Of npm's lifecycle scripts, three can fire from a dependency: preinstall, install, and postinstall. The part that matters is that this is not limited to your direct dependencies. Scripts belonging to a transitive dependency six levels down run with the same permissions, as the same user.

So the boundary you are defending is not "the packages I chose." It is "the entire tree the packages I chose dragged along." When an agent is adding dependencies, that boundary can widen overnight.

HookWhen it firesTypical legitimate use
preinstallBefore the package unpacksEnvironment checks (rarely needed)
installRight after unpackingBuilding native addons
postinstallAfter installFetching binaries, applying patches

The legitimate uses are real. Native addons and tools that fetch platform-specific binaries do not work without them. Which means "ban everything" is not a policy anyone sticks to. The policy that survives is: off by default, allowed by name.

Flipping the Default

Defaults and config locations differ by package manager. Here is what I actually set across four repositories.

ToolDependency scripts by defaultHow to block or allow
npmRunignore-scripts=true in .npmrc; run allowed ones manually
pnpm (v10+)Do not runOnly packages listed in pnpm.onlyBuiltDependencies run
Yarn (Berry)Do not runenableScripts / dependenciesMeta in .yarnrc.yml

If you are on pnpm, the safe default is already yours. You only need to be explicit about the allowlist.

{
  "pnpm": {
    "onlyBuiltDependencies": ["esbuild", "sharp", "@swc/core"]
  }
}

On npm, you invert the default yourself.

# .npmrc (repo root, committed)
ignore-scripts=true

The honest problem: some packages break under ignore-scripts=true. Anything that fetches a binary — sharp, esbuild — will fail. And it fails in an unhelpful way. The install succeeds. Then the app starts and tells you a binary is missing.

So reverse the order. Instead of hunting for breakage after the fact, count what will stop first. Across four repositories, the steps that worked for me were these three:

  1. Inventory every dependency in the tree that carries a script (Implementation 1)
  2. Sort that list into an allowlist and a drop-candidate list
  3. Flip the default and let only the allowlist through

Done in this order, you know the blast radius before you start. The first time I did it backwards, isolating the cause alone cost me half a day.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦The .npmrc and pnpm settings that stop install-time scripts by default, and how to find what breaks when you do
✦A working script that scores new dependencies on age, weekly downloads, name edit distance, and install scripts
✦A gate for unattended runs, plus one month of real numbers (87% auto-passed, 13% held, and where the false positives landed)
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

▣ App Dev2026-10-15
I Swapped an Immutable Asset at the Same URL, and Only the Browser Kept the Old Copy
Overwrite a long-cached JS file at the same URL and neither a CDN purge nor a refresh will make the browser fetch it again. Four delivery styles — same URL, no-cache, query string, content-hash filename — compared in Chromium, plus a complete build-step script that adds the hash.
▣ App Dev2026-09-29
Purging Cloudflare Didn't Bring Back the New Wallpapers: the Stale JPEGs Were Held by XPageSpeed on the Origin
An operations record from a wallpaper app: images overwritten at the same URL kept arriving stale even after a Cloudflare purge. Covers the three-way local/origin/edge probe that names the guilty layer, when prefix purge beats per-URL purge, and how to switch off Xserver's XPageSpeed in .htaccess without a 500.
▣ App Dev2026-09-19
I Asked for the Whole Quote PDF Tool at Once, Then Split It Into Four Requests
How I moved my client quote paperwork from copy-and-edit to a small PDF tool built with Antigravity, why the first single-shot request had to be thrown away, and the four smaller requests that replaced it, with working code.