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
Contents
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-scriptsdocs say: “Dependency install scripts are blocked by default.” The install ends with a list of skipped packages. You approve the ones you trust into theallowScriptsfield ofpackage.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-hashesto 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:
## 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.
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.
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:
□ 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 itQuick 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.

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.