Kousigan A

Coding agent dependencies: check the name before you approve

Before a coding agent adds a package, check it is needed, exists under that exact name, and what its licence, upkeep, install scripts and lockfile diff bring.

Last verified against official docs on

A coding agent that runs npm install or pip install has chosen a dependency for you. Before the package goes in, check that it is needed at all and that it exists under that exact name, then a human approves it. The name check matters because coding agents can suggest packages that do not exist, and an attacker can publish one under the suggested name.

The rest of the checks cover who maintains the package and its licence. They also cover what it pulls in, whether it runs code on install, and what the lockfile diff shows. They apply to Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI or any other agent, and most take one read-only command.

This is part 12 of the series. Part 4 listed new dependencies as one thing to verify in a change. This part covers the whole decision to add, upgrade or replace a package. The tool behaviour below comes from the official npm, pip, PyPI, GitHub and OpenSSF docs, last verified on 11 October 2026. The command output shown comes from npm view and a pip install --dry-run, run on 11 October 2026; nothing else was tested for this post.

First ask whether you need a package at all

A new package brings obligations with it. You take on code you did not write, and every package that code depends on. You take on its maintainers’ habits, its licence terms, any scripts it runs on install, and every future update and security advisory.

So before looking at any package, work down this list and stop at the first step that does the job:

standard library → a dependency you already have → a few lines of your own code → a new package

The npm registry sometimes answers the question for you. Running npm view left-pad deprecated prints the package’s deprecation message:

use String.prototype.padStart()

The package’s own registry entry tells you to use the standard library. Prompt 1 below asks the agent to show this step before it proposes anything.

Check the package exists under that exact name

Treat a package name from a coding agent as unchecked. Models can hallucinate package names that sound right and do not exist. The USENIX Security 2025 paper “We Have a Package for You!” tested 16 code-generating models on 576,000 code samples in Python and JavaScript. It found that “the average percentage of hallucinated packages is at least 5.2% for commercial models and 21.7% for open-source models”.

The names also come back. The authors re-ran prompts that had produced a fake name, ten times each. The arXiv version of the paper reports: “43% of hallucinated packages were repeated in all 10 queries, while 39% did not repeat at all”. A name that repeats is a name an attacker can register first. Trend Micro’s write-up calls this slopsquatting: “an evolution of the classic typosquatting attack. Rather than relying on human typographical errors however, attackers exploit AI-generated hallucinations instead.”

The first check is cheap. npm view <name> asks the registry about a package without installing it. For a name that is not on npm, it fails with this:

npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/<name> - Not found

For Python, pip index versions <name> lists the versions on the package index, and https://pypi.org/project/<name>/ shows the project page.

A hit needs a second check. Slopsquatting works because the name does exist: an attacker registered it. Also check that the repository link, the publisher and the release history match the project whose docs you were reading. A brand-new package under a name an agent suggested deserves a second look.

The checks before a new dependency goes in

Each check has a command that answers it without installing anything, or with a dry run:

Question npm Python (pip, PyPI) What to look for
Do you need it? npm ls lists what is already installed pip list lists installed packages something you already have, or the standard library, does the job
Does it exist under that exact name? npm view <name> pip index versions <name>, or the PyPI project page the repository and publisher you expected
Is it maintained? npm view <name> repository.url time.modified, then the repository the release history on the PyPI project page recent releases and commits, or a small, finished package
What is its licence? npm view <name> license the PyPI project page; pip show <name> once installed a licence your team accepts
What else does it pull in? npm view <name> dependencies; after install, npm ls --all and npm explain <dep> pip install --dry-run --ignore-installed --only-binary :all: <name> every transitive package, because each is code you now trust
Does it run code on install? npm view <name> scripts a source distribution can run code; --only-binary :all: refuses them preinstall, install or postinstall scripts
What changed in the lockfile? git diff package-lock.json git diff on your lock or requirements file only the packages you expected to change
How big is the version jump? npm view <name> versions and npm view <name> time pip index versions <name> a major version change, and its release notes

The commands come from the npm CLI docs and the pip docs, last verified on 11 October 2026.

Maintenance: a quiet package needs a closer look

The OpenSSF Scorecard Maintained check gives an archived project the lowest score. The highest goes to a project with “at least one commit per week during the previous 90 days”. Its own docs add a fair warning: “a lack of active maintenance is not necessarily always a problem”. A small utility can be finished. The docs say a quiet project “should signal that potential users should investigate further to judge the situation.”

Transitive dependencies: one install, several packages

A transitive dependency is a package your new package depends on, which you never asked for by name. A dry run shows them before anything is installed. Asking pip for requests alone, on 11 October 2026, ended with:

Would install certifi-2026.7.22 charset-normalizer-3.5.2 idna-3.20 requests-2.34.2 urllib3-2.8.0

One request, five packages. On npm, npm ls --all prints the whole installed tree. When a package in the lockfile looks unfamiliar, npm explain <dep> prints “the chain of dependencies causing a given package to be installed”.

Install scripts: code that runs before you read it

Install scripts are commands a package asks to run on your machine during the install, before any of your tests run. Package managers handle them differently:

  • npm 12 blocks them for dependencies. The npm approve-scripts docs say: “Dependency install scripts are blocked by default.” The install ends with a list of skipped packages. You approve the ones you trust into the allowScripts field of package.json, pinned to the version you reviewed.
  • npm 11 runs them. Its docs call the same field “advisory: install scripts still run by default”.
  • pip says in its secure installs docs that by default it “involves running arbitrary code from distributions”. It suggests --only-binary :all: to refuse source distributions and --require-hashes to check each file against a hash you recorded.

So check which npm version your project and your CI use. On npm 11, npm install --ignore-scripts stops the scripts. The install docs note that npm test and npm run still run the script you asked for.

Lockfiles and version jumps: read the lockfile diff

A one-line change in package.json can rewrite a large part of package-lock.json. When a range changes from ^7.0.0 to ^8.0.0, the npm install docs say npm re-resolves the tree and updates the lockfile to match. GitHub’s dependency review docs warn that if the updated package “also has updated dependencies, your pull request may have more changes than you expected.”

Treat a lockfile change that the manifest does not explain as a finding. The package-lock.json docs list “readable source control diffs” as one reason the file exists. For an upgrade, also read the release notes of every major version you cross.

The agent proposes a dependency, a human approves it

The approval rule is short: the agent may propose a package, and a person approves it. Put it in the rules file your agent reads (AGENTS.md, CLAUDE.md or your tool’s own file; Part 1 lists which agent reads which). An example section:

AGENTS.md (example)
## Dependencies

- Do not install, upgrade or remove packages. Propose the change and wait for approval.
- Before proposing a package, check the standard library, the existing
  dependencies and whether a few lines of code would do.
- For each proposal, give: the exact name and registry, why it is needed,
  evidence it exists, the licence, maintenance, new transitive dependencies,
  install scripts and the version.
- Do not edit lockfiles by hand.

A rules file is a request, not a guarantee. The agent reads it, and can still miss it, as Part 3 explains. The other layers are in other parts of this series:

  • Part 6: whether the agent may run an install command without asking.
  • Part 10: a dependency check in CI that blocks the merge.
  • Part 11: reading the dependency part of a diff in review.

On GitHub, the dependency review action can be that CI check. It can fail a pull request that adds a known-vulnerable package, or a licence outside your allow-licenses list.

A package’s own files can also carry text the agent reads as instructions. That is prompt injection, the subject of Part 7.

Two prompts: propose a dependency, review a dependency change

Both prompts keep the agent to read-only checks. Neither relies on a feature of one tool.

Prompt 1: propose a dependency, don’t install it

Use Prompt 1 with any task that might need a new package.

Prompt 1: propose a dependency, don't install it
Task: <describe the task>

Before adding any new package, check whether it is needed at all.

1. Check the standard library, the dependencies this project already has,
   and whether a few lines of code would do the job.
2. If a new package is still the best option, do not install it.
   Propose it.
3. For each package you propose, report:
   - the exact name and the registry (npm, PyPI, ...)
   - why the existing code and dependencies are not enough
   - evidence that it exists under that exact name, such as the output of
     npm view <name> or pip index versions <name>
   - the repository URL and the date of the latest release
   - the licence
   - the transitive dependencies it would add
   - any install scripts (preinstall, install, postinstall)
   - the version you propose, and why
4. If you cannot confirm that a package exists under that exact name,
   say so. Do not suggest a similar-looking name instead.

Use only read-only commands for these checks.
Do not install, upgrade or remove packages, and do not edit package.json,
lockfiles or requirements files.
Never print, expose or commit secret values.
Do not commit, push, deploy, run destructive commands or make external
changes unless I explicitly authorise it.
If two reasonable attempts fail, stop and report the failure rather than
repeatedly guessing.

Then wait for my approval.

Prompt 2: review a dependency change

Use Prompt 2 on an upgrade, a replacement or any diff that touches a manifest or a lockfile.

Prompt 2: review a dependency change
Change to review: <the branch, commit or diff>

Review only the dependency changes in this change.

1. List every package added, removed or changed, in the manifest and in
   the lockfile, direct and transitive.
2. For each version change, say whether it is a major, minor or patch
   change, and summarise any breaking changes from the release notes.
3. Flag any lockfile change that the manifest change does not explain.
4. For each new package, report its licence, its install scripts and its
   repository.
5. If the project has an audit command (such as npm audit), run it and
   report the result.
6. Say what you could not check.

Do not change any files. Do not install, upgrade or remove packages.
Never print, expose or commit secret values.
Do not commit, push, deploy, run destructive commands or make external
changes.
If two reasonable attempts fail, stop and report the failure rather than
repeatedly guessing.

Report findings with evidence.

npm audit “submits a description of the dependencies configured in your project to your default registry”, so skip step 5 where that is not allowed.

A checklist before you approve a new dependency

The approval checklist turns the dependency checks into yes-or-no questions for whoever approves the package:

Before you approve a new dependency
□ The standard library and existing dependencies can't do the job
□ A few lines of your own code can't do it either
□ The exact name exists in the right registry
□ The repository, publisher and release history are the ones you expected
□ It is maintained, or small and finished
□ Its licence is one your team accepts
□ You know the transitive dependencies it adds
□ You know whether it runs install scripts
□ The lockfile diff shows only what you expected
□ You have read the release notes for any major version jump
□ A person approved it

Quick answers

What is slopsquatting?

Slopsquatting is a supply-chain attack in which someone publishes a package under a name that AI models invent, and often repeat. A developer or a coding agent who installs the suggested package then gets the attacker’s code instead of a missing-package error.

Is an unmaintained package always a risk?

An unmaintained package is not automatically a problem, because a small utility can be finished. The OpenSSF (Open Source Security Foundation) Scorecard docs treat a quiet project as a signal to investigate further.

How do you check an npm package exists before installing it?

The command npm view <name> looks the package up in the npm registry without installing anything. When no package has that name, it fails with an E404 error. A match still needs checking: confirm the repository, publisher and release history.

Does npm run install scripts from dependencies?

npm 12 blocks dependency install scripts by default and lists the skipped packages, which you approve with npm approve-scripts. In npm 11 they still run by default, and the --ignore-scripts option turns them off.

What is a transitive dependency?

A transitive dependency is a package that one of your dependencies needs, installed without you naming it. Tools such as npm ls --all, npm explain and pip install --dry-run show which transitive packages a new dependency brings in.

More on AI coding is in the AI category.

Cartoon of Kousigan making a heart with his hands

Kousigan A

Build with AI. Ship with care.

Software engineer building real products with AI assistants. I write down what works: prompts, rules, skills and agents, and how to ship safely.