AI Coding Agents and Supply Chain Risk: How to Verify Dependencies Before Merging
When an AI coding agent adds a dependency to your project, it does not tell you whether that package is maintained, whether it has known vulnerabilities, or whether it was published by a trustworthy author. It just adds the line to your requirements, package.json, or go.mod — and if you merge without checking, you have just given a stranger’s code a direct path into your production system.
Supply chain attacks on software dependencies are not theoretical. In the last few years, we have seen:
- typosquatting attacks where malicious packages mimic popular ones with slight name variations
- dependency confusion attacks where internal package names are registered on public registries with malicious payloads
- maintainer compromise where legitimate packages are hijacked to deliver malware
- protestware where maintainers intentionally break their own packages to make a statement
AI coding agents make all of these risks worse because they add dependencies faster than most teams can verify them. This article gives you a practical framework for catching dependency risk before it reaches production — whether you use Copilot, Cursor, Claude Code, or any other AI coding tool.
Why AI agents make dependency risk worse
AI coding agents do three things that increase supply chain risk:
1. They add dependencies you did not ask for
You ask an AI agent to „add date formatting” and it installs moment (deprecated, 300KB), date-fns (tree-shakeable, modern), and dayjs (lightweight alternative) — then uses whichever one it prefers. You may not even notice the extras until you audit package.json or requirements.txt.
In one real-world pattern, developers asked AI agents to fix a small bug and received a PR that added 3-5 new dependencies, none of which were necessary for the fix. The agent had learned from training data that included these imports and „helpfully” included them.
2. They cannot distinguish between a well-maintained package and a compromised one
AI models do not check npm download counts, GitHub star trends, last-commit dates, or known CVEs. They pattern-match on names and import statements. If event-stream appeared in training data, the agent will suggest it — even though that package was famously compromised in 2018.
3. They create transitive dependency trees you cannot see
When an agent adds one package, it pulls its entire dependency tree. A single line in package.json can bring in 50+ transitive dependencies. Most developers never check beyond the direct dependency. The agent certainly does not.
The dependency verification checklist for AI-generated code
Before you merge any AI-generated change that adds or modifies dependencies, run this checklist. It takes under 15 minutes for most PRs and catches the most common supply chain risks.
Check 1: Did the AI add any dependencies you did not explicitly request?
What to look for:
- Compare the dependency diff against the task description
- Look for packages that were not mentioned in your request
- Check for version pinning versus loose ranges (
^1.2.3vs>=1.0.0)
Quick test:
# For Node.js projects: show what changed in package.json
git diff main...HEAD -- package.json package-lock.json
# For Python projects: show what changed in requirements
git diff main...HEAD -- requirements.txt setup.py pyproject.toml Pipfile
# For Go projects
git diff main...HEAD -- go.mod go.sum
If the diff shows dependencies that are not obviously required for the task, flag them. AI agents frequently add „helper” packages that introduce unnecessary attack surface.
When to escalate: If the agent added more than 2-3 unexpected dependencies, reject the change and ask for a minimal implementation that uses existing packages or the standard library.
Check 2: Is each added package real, maintained, and from a trusted source?
What to verify for each new dependency:
- Does the package actually exist on the registry? Typosquatting attacks use names that look similar to popular packages. Check the exact spelling against
npmjs.com,pypi.org, or the relevant registry.
- When was it last updated? A package with no updates in 2+ years may be abandoned, which means unpatched vulnerabilities and no maintainer response to security reports.
- How many downloads does it have? A package with fewer than 1,000 weekly downloads on npm (or equivalent on other registries) is risky. Low download counts mean few eyes on the code and slow vulnerability discovery.
- Does it have known security advisories? Check
npm audit,pip audit, or GitHub Dependabot alerts for known CVEs.
- Who maintains it? Packages maintained by a single unknown developer are higher risk than those maintained by a recognized organization or a team with a track record.
Quick verification script (Node.js):
# Check if package exists and get basic stats
npm view description version repository
npm view time --json | head -5
# Check for known vulnerabilities
npm audit --production
Quick verification script (Python):
# Check package metadata
pip index versions
# Check for known vulnerabilities
pip-audit --desc
# Or use safety check
safety check --json
Check 3: Are there transitive dependency risks you cannot see?
Direct dependencies are only the surface. The real risk is in the dependency tree below.
What to do:
- Run a dependency tree audit before and after the AI-generated change
- Compare the trees to identify new transitive dependencies
- Check if any transitive dependency is known-vulnerable or unmaintained
Quick test:
# Node.js: show the full dependency tree
npm ls --all --long
# Python: show dependency tree
pipdeptree
# Go: show module dependencies
go mod graph
When to escalate: If the agent’s change adds more than 10 transitive dependencies, consider whether the functionality can be achieved with a lighter alternative or standard library code.
Check 4: Are dependency versions pinned or loose?
AI agents often generate loose version ranges because training data contains many examples of ^version and >=version patterns. Loose ranges are convenient but dangerous:
^1.2.3allows any 1.x.y version — including a future 1.3.0 that introduces a vulnerability>=1.0.0allows any version — including a malicious 99.0.0 published by a compromised maintainer*orlatestallows any version, including breaking changes and compromised releases
Best practice: Pin exact versions in production dependencies. Use lockfiles (package-lock.json, Pipfile.lock, go.sum) and commit them to version control.
Quick test:
# Check for loose version ranges in requirements.txt
grep -E '(>=|~=|>|<|\*)' requirements.txt
# Check for unpinned dependencies in package.json
cat package.json | python3 -c "
import json, sys, re
data = json.load(sys.stdin)
for dep_type in ['dependencies', 'devDependencies']:
for name, ver in data.get(dep_type, {}).items():
if ver in ['latest', '*'] or ver.startswith('>=') or ver.startswith('^'):
print(f'{dep_type}: {name}={ver} (loose range)')
"
Check 5: Did the AI modify lockfiles or checksums in unexpected ways?
Lockfiles and checksum files are your integrity verification layer. If an AI agent modifies them without a clear reason, it may be:
- Downgrading a dependency to a vulnerable version
- Removing integrity checks
- Replacing checksums to match a compromised package
What to check:
package-lock.jsonchanges that downgrade version numbersPipfile.lockchanges that remove hash entriesgo.sumchanges that modify existing checksums- Any removal of integrity fields (
integrityin npm,--hashin pip)
Quick test:
# Check if integrity hashes were removed from package-lock.json
git diff main...HEAD -- package-lock.json | grep -c "integrity"
# Check if hashes were removed from Pipfile.lock
git diff main...HEAD -- Pipfile.lock | grep -c "sha256:"
# Check go.sum for modified checksums (not just additions)
git diff main...HEAD -- go.sum | grep "^-"
Check 6: Can you generate an SBOM (Software Bill of Materials) for this change?
An SBOM is a list of all components in your software, including version numbers and dependency relationships. It is becoming a compliance requirement in many industries and is essential for incident response.
How to generate an SBOM:
# Node.js
npm sbom --sbom-type spdx > sbom-spdx.json
# Python (using cyclonedx-bom)
pip install cyclonedx-bom
cyclonedx-py requirements -i requirements.txt -o sbom.xml
# Go
go mod graph | cyclonedx-go -o sbom.json
Even if you do not currently need an SBOM for compliance, having one means you can quickly answer „are we affected by vulnerability X?” when a new supply chain attack is disclosed.
Practical workflow: Dependency verification in your review process
Here is how to integrate these checks into your existing code review workflow:
Before the review
- Generate the dependency diff automatically. Add a CI step that compares
package.json,requirements.txt, orgo.modbefore and after the PR.
- Run automated vulnerability scanning. Use Dependabot, Snyk,
npm audit,pip-audit, or equivalent tools as a required CI check.
- Flag any PR that adds more than N new dependencies. Set a threshold (we recommend 3-5 for small teams) and require explicit justification for exceeding it.
During the review
- Verify each new dependency against the checklist above. For AI-generated PRs, this is not optional — the agent did not verify them for you.
- Check if the dependency is actually necessary. Can the functionality be achieved with the standard library or an existing dependency?
- Look for alternative packages that are more maintained, lighter, or more widely trusted. AI agents often suggest the first package they learned about, not the best one.
After the review
- Update your SBOM with the new dependencies.
- Add the dependency to your internal allowlist if you maintain one.
- Set up monitoring for vulnerability advisories on the new package.
CI gate: Automated dependency verification for AI-generated PRs
For teams that use CI, here is a GitHub Actions workflow that runs dependency checks automatically:
# .github/workflows/dependency-gate.yml
name: Dependency Verification Gate
on:
pull_request:
paths:
- 'package.json'
- 'package-lock.json'
- 'requirements.txt'
- 'Pipfile.lock'
- 'go.mod'
- 'go.sum'
jobs:
dependency-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for new dependencies
run: |
# Count new dependencies added in this PR
NEW_DEPS=$(git diff origin/main...HEAD -- package.json | grep -c '^\+' | head -1 || echo "0")
echo "New dependency additions detected: $NEW_DEPS"
if [ "$NEW_DEPS" -gt 5 ]; then
echo "::warning::More than 5 dependency additions — please verify each one"
fi
- name: Run npm audit
if: hashFiles('package-lock.json') != ''
run: npm audit --production --audit-level=high
continue-on-error: false
- name: Run pip-audit
if: hashFiles('requirements.txt') != ''
run: |
pip install pip-audit
pip-audit --desc -r requirements.txt
continue-on-error: false
- name: Check for loose version ranges
run: |
echo "Checking for loose version constraints..."
# Node.js
if [ -f package.json ]; then
LOOSE=$(cat package.json | python3 -c "
import json, sys
data = json.load(sys.stdin)
loose = []
for dep_type in ['dependencies', 'devDependencies']:
for name, ver in data.get(dep_type, {}).items():
if ver in ['latest', '*'] or ver.startswith('>='):
loose.append(f'{name}={ver}')
print('\n'.join(loose))" 2>/dev/null || echo "")
if [ -n "$LOOSE" ]; then
echo "::warning::Loose version ranges found: $LOOSE"
fi
fi
# Python
if [ -f requirements.txt ]; then
LOOSE_PY=$(grep -cE '(>=|~=|>|<|\*)' requirements.txt || echo "0")
if [ "$LOOSE_PY" -gt 0 ]; then
echo "::warning::$LOOSE_PY loose version ranges found in requirements.txt"
fi
fi
This gate does three things:
- Warns when more than 5 dependencies are added in a single PR
- Fails the build on high-severity vulnerabilities
- Flags loose version ranges that could allow supply chain attacks
Real-world examples of dependency risk in AI-generated code
Example 1: The "helper" package that was never needed
A developer asked an AI agent to add input validation to a Flask endpoint. The agent's response included:
+ from flask_wtf.csrf import CSRFProtect
+ from werkzeug.security import generate_password_hash
+ from markupsafe import escape
+ import bleach
The task only needed markupsafe.escape. The agent added bleach (a full HTML sanitizer, unnecessary for plain escaping), flask_wtf (adds CSRF protection, not requested), and werkzeug.security (password hashing, not related to input validation). Each unnecessary dependency expands the attack surface.
Example 2: Typosquatting close call
An AI agent suggested importing reqeusts instead of requests. The typo is one transposed letter, and reqeusts is exactly the kind of name a typosquatter would register. If merged without verification, it could execute arbitrary code at import time.
Example 3: The deprecated dependency
An AI agent suggested using pycrypto for encryption. This package has been unmaintained since 2013 and has multiple known CVEs. The correct modern alternative is cryptography. But the agent's training data still contains many examples of pycrypto imports, so it keeps suggesting it.
How CodeRiskTools helps with dependency verification
The CodeRiskTools review kit includes a structured dependency verification section as part of the pre-merge checklist. The Basic kit covers the five-check review pass that includes a security check for dependency risks. The Pro kit adds:
- Expanded risk review prompts specifically for dependency and supply chain verification
- Risk scoring workflow that rates dependency additions by severity (Low through Critical)
- Client-ready summaries that document dependency review findings for stakeholders
If your team is regularly reviewing AI-generated PRs that add dependencies, the structured prompts and scoring workflow help you catch risks systematically instead of hoping you notice them.
→ See Basic details — five-check review pass including dependency verification
→ See Pro details — expanded dependency prompts, risk scoring, and client-ready summaries
Key takeaways
- AI agents add dependencies without verification. They pattern-match on training data, not on package safety metrics. Every AI-added dependency needs human review.
- Check all five dimensions: necessity, maintenance status, transitive tree, version pinning, and lockfile integrity. Missing any one of these leaves a gap.
- Pin your versions. Loose version ranges are an invitation for supply chain attacks. Use exact versions and lockfiles in production.
- Automate what you can. CI gates for dependency count, vulnerability scanning, and loose version detection catch the easy stuff. Human review catches the rest.
- Generate and maintain an SBOM. When a supply chain vulnerability is disclosed, you need to answer "are we affected?" in minutes, not days.
- Treat every AI-added dependency as untrusted until verified. The agent did not check it. That means you have to.
Related reading
- How to review AI-generated code before you merge it — the five-check pre-merge review pass
- AI code review checklist for small software teams — seven-question checklist for structured AI code review
- CI gates for AI-generated code — how to build CI gates that catch risky AI patterns before production
- Secret scanning for AI-generated code — why your diff might be leaking API keys
- Agentic coding risk review: a practical workflow for teams — the full review workflow for AI coding agent changes


