post: Install-Script Permissions Can Outlive a Dependency_□×

Install-Script Permissions Can Outlive a Dependency

The wiki project had stopped generating embeddings locally, but its pnpm configuration still allowed install scripts for @xenova/transformers.

The package wasn’t in the lockfile. The permission was still there.

Nothing was running on behalf of an absent package. The concern was what the configuration would allow if that package returned through a future dependency change.

A permission can survive the code that needed it

The relevant part of pnpm-workspace.yaml looked like this:

allowBuilds:
  sharp: true
  "@xenova/transformers": true

Both entries allowed dependency install scripts. Only one still corresponded to a package in the resolved tree.

The Transformers entry came from an earlier local-embedding implementation. Search had moved to a hosted retrieval service, but removing that implementation hadn’t removed the build permission.

An install script runs code with the permissions available to the install process. I want an approval for that code to have a current reason, not just a plausible explanation of something the project used to do.

The stale entry wasn’t evidence of an exploit. It was an approval that could apply again without prompting a fresh decision if the package reappeared.

The manifest wasn’t enough to check the other entry

Sharp wasn’t a direct dependency either, but it remained in the tree through Astro’s optional image dependency. Its absence from package.json didn’t make its build permission stale.

The workspace also had a Sharp version override. The override and the build approval controlled different things: one constrained dependency resolution, while the other allowed install scripts.

That made the lockfile and dependency chain necessary parts of the review. Looking only at direct dependencies would have grouped Sharp with the absent Transformers package, even though their situations were different.

I don’t want a cleanup rule that removes permissions just because a package isn’t listed directly. It needs to establish whether the resolved installation still includes the package and why the approval exists.

Explicit denials also have a purpose

The configuration included false entries for packages whose build scripts the project didn’t want to run.

Those entries aren’t unused permissions. They record denials. A package being absent today doesn’t necessarily make a deliberate denial worth deleting.

The pnpm settings also need to be described accurately. allowBuilds and strictDepBuilds both existed in pnpm 10. The pnpm 11 migration removed older settings in favor of the map; it didn’t invent explicit build decisions.

With strict checking enabled, an unreviewed dependency build causes installation to fail. The map can record either approval or denial so the decision isn’t left implicit.

Review the grants when dependencies change

The useful follow-up is a review check for positive grants that no longer match the resolved dependency graph. I would make that a prompt to investigate, not an automatic deletion.

Package matchers can cover versions or multiple packages. A future-facing approval might be intentional. If so, it needs a reason that survives scrutiny better than “this used to be installed.”

For this project, the local-embedding dependency was gone and the old approval deserved removal. The Sharp entry needed review against the transitive dependency that was still present.

Dependency cleanup isn’t finished at package.json. Build permissions and overrides can preserve decisions long after the code that motivated them has left.

Sources

I’d appreciate a follow. You can subscribe with your email below. The emails go out once a week, or you can find me on Mastodon at @[email protected].

START
llbbl.exeprojects/posts/experiments/subscribe.dlg
© 2026v1.0.0