An AI coding agent can produce a clean-looking diff while quietly expanding the software supply chain. It may add a library because it remembers a familiar solution, regenerate a lockfile with hundreds of indirect changes, copy a package name that is one character away from the intended project, or declare the task complete without proving that the new code needs the dependency at all.
The review problem is therefore larger than “does the code compile?” A dependency change is a claim about architecture, identity, versions, security, legal permissions, build inputs, and future maintenance. Each claim needs evidence in the diff or in a primary source. Fluent explanations are not evidence.
This guide turns a recurring complaint about AI coding tools—extra changes, invented interfaces, and premature completion claims—into a dependency inspection method. It complements How to Review AI-Generated Code, which starts with task fit and behavioral correctness. Here the unit of review is every new, changed, or removed component in the resolved dependency graph.
The central rule is simple:
Do not approve the dependency because the agent sounds confident. Approve only the smallest dependency graph that is supported by inspectable change evidence.
This article does not decide who owns copyright in AI-generated code. That question depends on facts and law outside a package diff. The narrower review asks what changed, which third-party material entered the graph, what license and provenance records are available, and whether the repository can verify the resulting build.
The dependency change contract
Before reading package metadata, compare the pull request with the original task. A reviewer should be able to complete this sentence:
“To satisfy requirement X, this change uses component Y at resolved version Z, and the repository demonstrates that choice with evidence E.”
If X, Y, Z, or E is missing, the review is not ready for an approval decision. A passing test suite can show that observed behavior matched the tests. It does not prove that the package was necessary, correctly identified, appropriately licensed, maintained, or produced by the claimed build.
| Review question | Evidence that can answer it | Evidence that cannot answer it alone |
|---|---|---|
| Was a dependency required? | Call sites, before-and-after design, rejected standard-library or existing-library option | Agent explanation saying the package is “best practice” |
| What package entered the graph? | Manifest diff, lockfile diff, registry namespace, source-repository link | A similar-looking import name |
| What version will be used? | Resolved lockfile entry or equivalent resolver output | A broad manifest range by itself |
| Is a known vulnerability reported? | Advisory database result tied to the exact ecosystem, name, and version | “No CVE found” without naming the data source and scan time |
| What license evidence exists? | Package metadata, license file, SPDX identifier or expression, counsel-approved policy result | Repository topic, README badge, or assumption based on popularity |
| How was the artifact produced? | Verifiable provenance or artifact attestation bound to a digest | A release page saying “built securely” |
| Can it be removed? | Reverted manifest and lockfile change plus tests or an isolated replacement | An agent’s claim that it is lightweight |
GitHub’s supply-chain documentation distinguishes direct dependencies named by a project from transitive dependencies pulled in by those direct dependencies. Its dependency graph derives data from manifests and lockfiles, and it notes that build-time resolution can require dependency submission for a more complete graph. That distinction matters because a one-line manifest edit can produce a much larger effective change. Source: https://docs.github.com/en/code-security/concepts/supply-chain-security/supply-chain-security
Eight separate things reviewers must not collapse
The fastest way to miss risk is to treat “the dependency” as one object. Review it through eight separate lenses.
| Lens | What it means | Minimum review record |
|---|---|---|
| Direct dependency | Explicitly requested by the project in a manifest or equivalent | Name, requested range, intended call site, owner |
| Transitive dependency | Introduced through another component | Parent path, resolved version, runtime or build role |
| Manifest | Human-authored intent and version constraints | Exact changed lines and rationale |
| Lockfile | Resolver-selected graph, often including integrity data | Added, removed, and changed nodes; unexplained churn |
| Known vulnerability | Publicly reported issue mapped to package identity and version | Source, query time, affected range, fix or mitigation |
| License | Declared permissions and conditions for a component | Identifier or text location, policy result, exceptions |
| Maintenance | Evidence about ongoing project stewardship | Release history, repository activity, security policy, ownership changes |
| Provenance | Evidence about where and how an artifact was built | Subject digest, signer or builder identity, source and workflow reference |
Two more lenses cut across all eight:
- Build-only exposure: A formatter, compiler plugin, bundler, code generator, test runner, or documentation tool may never ship in the runtime artifact, yet it can execute during a privileged build and influence the output. “Dev dependency” is a deployment label, not a security exemption.
- Removal: The dependency should have an exit path. If its use can be replaced by a few stable lines, an existing project utility, or a platform API already in scope, the package may be unnecessary graph growth.
For agent permissions and tool boundaries around package operations, see Sandbox AI Coding Agents Without Blocking Useful Work and MCP Security Checklist. An agent that may edit source does not automatically need authority to install packages, execute package lifecycle scripts, publish artifacts, or change CI.
Manifest and lockfile are different evidence
A manifest records requested constraints and dependency categories. A lockfile records a resolver’s selected graph for a particular tool and format. Review both, because each can hide a different failure.
In the npm ecosystem, package.json expresses project metadata and dependency requests, while package-lock.json describes the exact generated tree so later installs can reproduce that tree. Cargo documents Cargo.toml as the manifest and Cargo.lock as exact dependency information. Python’s packaging specification defines pylock.toml for reproducible installation. NuGet can generate packages.lock.json containing the full dependency closure. Go uses go.mod for module requirements and go.sum for cryptographic hashes of direct and indirect module content. Maven resolves transitive dependencies from POM metadata and applies scopes. Official references appear in the Sources section.
| Ecosystem | Intent or manifest evidence | Resolution or integrity evidence | Review trap |
|---|---|---|---|
| npm | package.json | package-lock.json or the repository’s selected lock format | A small request can rewrite unrelated nodes if the wrong tool version is used |
| Python | pyproject.toml or approved requirements input | pylock.toml or the repository’s established lock format | Environment markers and extras can change the graph by platform |
| Rust | Cargo.toml | Cargo.lock | Feature flags can add code and transitive packages without a new top-level name |
| Go | go.mod | go.sum plus the selected module graph | A checksum proves content consistency, not suitability or license approval |
| Maven | pom.xml and dependency management | Resolved dependency tree and repository metadata | Scope and exclusions can change what reaches compile, test, or runtime paths |
| NuGet | Project PackageReference items | packages.lock.json when enabled | Floating versions can resolve differently until the graph is locked |
The reviewer should reject unexplained lockfile churn. “The package manager did it” describes a mechanism, not a rationale. Ask why unrelated packages moved, whether the repository-standard tool and version produced the file, and whether the diff can be regenerated from only the intended manifest edit.
Do not hand-edit a lockfile merely to make the diff smaller. Regenerate it using the repository’s documented process in a controlled environment, then inspect the result. If the task does not authorize installation or external execution, the appropriate result is a blocked verification note, not a fabricated clean lockfile.
Direct and transitive dependencies need different questions
For a direct dependency, the primary question is necessity: why did the contributor choose this component? For a transitive dependency, the primary question is path: which parent introduced it, and is that path expected?
| Dependency class | Questions to ask | Typical evidence |
|---|---|---|
| Direct runtime | Is there a real call site? Is an existing component sufficient? Is the API used actually present in the pinned version? | Diff, local type information, official versioned documentation, focused tests |
| Direct development | Does it execute in build, test, generation, lint, or documentation? What permissions and inputs does it receive? | Build configuration, lifecycle-script review, sandbox record |
| Transitive runtime | Which direct parent requires it? Does it reach the shipped artifact? | Lockfile parent path, bundler or packaging inventory, SBOM |
| Transitive build | Does it execute or only supply data? Can it alter generated output? | Build graph, resolved build inputs, provenance record |
| Optional or feature-gated | Which feature, extra, platform marker, or profile activates it? | Manifest feature configuration and environment matrix |
| Test-only | Can it access secrets, network, repository write permissions, or release credentials in CI? | Workflow permissions and test command boundary |
Transitive does not mean unimportant. GitHub’s documentation says dependency review can show indirect changes represented in lockfiles, while its dependency graph documentation explains that dependencies resolved only during builds may require automatic or manual submission. Sources: https://docs.github.com/en/code-security/concepts/supply-chain-security/dependency-review and https://docs.github.com/en/code-security/concepts/supply-chain-security/dependency-graph-data
When an AI agent says “only one package was added,” count resolved nodes, not just manifest lines.
Known vulnerabilities: precise identity before severity
A vulnerability lookup is meaningful only when it binds four fields:
- ecosystem;
- normalized package name;
- resolved version or commit;
- advisory source and observation time.
OSV describes a schema that maps vulnerabilities to open-source package versions or commit hashes and aggregates sources that adopt the OSV format. GitHub compares dependency data with its advisory database for Dependabot alerts. A package-manager-native audit may add ecosystem-specific resolution. None of these sources can prove the absence of an undisclosed vulnerability.
| Result | Reviewer action | Required note |
|---|---|---|
| Resolved version falls in an affected range | Reject or require a documented, tested mitigation and owner-approved exception | Advisory ID, affected range, reachable role, proposed fixed version |
| Advisory matches a name but not the ecosystem | Correct the identity before deciding | Why the original match was false |
| No known advisory is returned | Continue other checks | Source and timestamp; state that the result covers known records only |
| Version is unresolved | Stop the vulnerability decision | Missing lock or build-resolution evidence |
| Scanner cannot parse the ecosystem or file | Use an approved alternate source or manual lookup | Coverage gap and remaining uncertainty |
| Advisory has no fixed version | Consider removal, isolation, or replacement | Exposure, compensating control, decision owner |
Do not let an agent convert “the scanner returned zero findings” into “the package is secure.” The first is an observation about a data source at a time. The second is a conclusion the observation cannot support.
Use Machine Gates for AI Output for deterministic checks such as “every dependency diff has an advisory result.” Keep the qualitative decision—whether the component is necessary and whether the exposure is acceptable—with a responsible reviewer, as described in Human-in-the-Loop AI Agents.
License review: record, do not improvise legal conclusions
SPDX provides a standard license list with identifiers, names, text, and canonical URLs, and its specification can represent software components, relationships, and licensing information. An SPDX identifier makes records easier to compare; it does not decide whether a license is compatible with your product, distribution model, linking method, or obligations.
For each new component:
- locate the license declared in package metadata;
- inspect the license file in the exact source or artifact version when available;
- record an SPDX identifier or expression only when the evidence supports it;
- note multiple licenses, exceptions, generated code, vendored components, and “license reference” cases;
- apply the organization’s approved-license policy;
- escalate ambiguity instead of asking the AI to invent a compatibility conclusion.
| License evidence state | Decision posture | Why |
|---|---|---|
| Clear identifier and matching text, allowed by policy | Continue to the rest of review | Identity still needs confirmation; license approval is not security approval |
| Multiple licenses with an explicit choice | Record the selected expression and conditions | The reviewer must know which option governs use |
| Metadata and repository text disagree | Reject pending clarification | A badge or registry field cannot safely override conflicting text |
| No license evidence | Reject normal consumption | Publicly readable source is not the same as permission to use |
Custom terms or an SPDX LicenseRef | Escalate to the designated legal or policy owner | Automated classification is insufficient |
| Copyleft, source-offer, notice, patent, or network-use condition is relevant | Apply the organization’s distribution-specific process | Compatibility depends on use and distribution facts |
Keep this review focused on observable third-party inputs. Do not infer a broad copyright result for the AI-authored glue code. Record the human-authored task, agent output diff, subsequent human edits, tests, package licenses, source references, and build evidence. Those records are useful regardless of how a later legal analysis classifies the code.
Maintenance status is evidence, not a popularity contest
A maintained project can still be unsuitable, and a quiet project can be stable. Avoid one-number judgments. OpenSSF Scorecard evaluates repository security practices, but its own description frames scores as information for a consumer’s trust and risk decision, not a universal approval verdict. Source: https://openssf.org/scorecard/
Collect a small, reviewable maintenance record:
- date and substance of the latest relevant release;
- whether the source repository and package registry point to each other;
- security policy or vulnerability reporting route;
- response to recent security issues when applicable;
- maintainer or namespace ownership changes;
- supported runtime versions;
- release and deprecation policy;
- unresolved issues that match your intended use;
- automated score or badge details, including the individual checks rather than only an aggregate.
| Signal | Helpful interpretation | Unsafe shortcut |
|---|---|---|
| Recent release | The release process is active | “Recent means secure” |
| Long gap with stable scope | May be mature and intentionally quiet | “Old means abandoned” |
| Many open issues | Needs context about project size and triage | “Issue count measures quality” |
| Security policy | Provides a reporting route | “A policy proves fast remediation” |
| OpenSSF Scorecard checks | Surfaces repository practice evidence | “A score above a chosen number auto-approves” |
| Ownership transfer | Requires identity and release-history scrutiny | “The familiar package name is enough” |
If maintenance evidence is weak but the dependency is small, the removal test becomes more important. The lowest-risk package may be the package you do not add.
Typosquatting and package identity
Typosquatting review begins before vulnerability and license review, because a correctly analyzed wrong package is still the wrong result. OpenSSF’s package repository security principles explicitly include steps to prevent typosquatting, such as namespacing or similar-name detection, as a package-repository capability. Source: https://repos.openssf.org/principles-for-package-repository-security.html
For every new name, compare:
- exact spelling, separators, scope, and letter case used by the ecosystem;
- registry publisher or organization;
- source repository linked from the registry;
- source repository’s link back to the registry;
- expected documentation domain;
- release history and first-publish date;
- package contents and lifecycle scripts;
- provenance or registry signature information when the ecosystem provides it.
Common warning patterns include a missing scope, swapped characters, singular versus plural, extra separators, a new package with the name of a familiar import, or metadata that points to a copied README but a different source repository. Do not ask the agent to “pick the closest name.” Ask it to show the exact primary-source identity.
npm documents provenance views that can expose build environment, workflow run, source commit, build file, and a transparency-log entry for packages published with provenance. npm also documents a signature and provenance audit command, but its prerequisites include installing dependencies. That command should therefore run only inside the repository’s approved dependency-verification process, not as an unapproved side effect of reviewing a name. Source: https://docs.npmjs.com/viewing-package-provenance/
Build-only dependencies are still supply-chain inputs
Runtime inventories often omit what made the artifact. That creates a blind spot for compilers, code generators, preprocessors, bundler plugins, test instrumentation, container builders, and downloaded scripts.
SLSA describes provenance as verifiable information about where, when, and how an artifact was produced. Its current specification separates build and source tracks and includes provenance among recommended attestation formats. GitHub artifact attestations are signed claims that can establish build provenance or associate an SBOM with an artifact. GitHub explicitly notes that attestations do not prove security; they provide information about where and how software was built. Sources: https://slsa.dev/spec/v1.2/ and https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations
| Build-input question | Evidence to retain |
|---|---|
| What executed? | Resolved package or tool identity and version |
| What source configured it? | Reviewed build file and commit |
| What could it read? | Checkout, environment, secrets, caches, and network policy |
| What could it write? | Generated source, binary, package, image, or release asset |
| Which builder ran it? | Builder identity and workflow run |
| Which inputs resolved at build time? | Provenance resolvedDependencies, dependency submission, or equivalent inventory |
| Which output was produced? | Subject name and cryptographic digest |
| Can a consumer verify it? | Attestation verification result and trust policy |
An SBOM and an attestation answer different questions. An SBOM inventories components and relationships. Provenance describes production. A signature or attestation binds a claim to an identity and artifact; the reviewer must still decide whether that identity and builder are trusted for this repository.
GitHub can export a repository dependency graph as an SPDX-compatible SBOM containing information such as versions, package identifiers, licenses, and transitive paths. It does not include downstream dependents. Source: https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/establish-provenance-and-integrity/export-dependencies-as-sbom
Six fictional pull requests and how to review them
The following pull requests are deliberately fictional. Package names use reserved example-style namespaces and must not be interpreted as real installation recommendations. The point is the review decision, not the package.
| PR | Proposed change | Evidence presented | Reviewer decision |
|---|---|---|---|
| PR 1: “Parse three config fields” | Adds direct runtime package @example-labs/config-shape and 18 resolved nodes | Agent says manual parsing is error-prone; no comparison with existing parser | Reject pending necessity proof; ask for the existing utility comparison and a no-new-dependency implementation |
| PR 2: “Upgrade HTTP helper” | Changes one direct version and 47 lockfile nodes | Focused tests pass; lockfile was produced with an unspecified tool version | Reject the current artifact; regenerate with the documented tool, explain transitive changes, then rescan exact versions |
| PR 3: “Faster documentation build” | Adds example-doc-transform as development-only with an install script | Benchmark is local; workflow has write permission and a release token | Reject until the build is sandboxed, permissions are reduced, script content and provenance are reviewed, and benefit is reproduced |
| PR 4: “Add spreadsheet export” | Adds example-sheet-writer; metadata says one license while source archive includes custom terms | Feature tests pass | Reject for conflicting license evidence; do not let behavioral tests override unresolved permission terms |
| PR 5: “Use familiar validation library” | Adds exampl-validator, one character away from the task’s named component | Registry page has a copied description and no verifiable source link | Reject as an identity failure; do not install or execute it while investigating |
| PR 6: “Remove unused date utility” | Deletes direct manifest entry but leaves imports and resolved transitive nodes through another package | Agent reports “dependency removed” | Reject the completion claim; map remaining parent paths, remove or document call sites, and prove the shipped graph changed |
PR 1: unnecessary direct dependency
Start at the call site. If the package is used for a stable, narrow operation already available in the language or repository, ask for the simpler change. The rejection is not “small packages are bad.” It is “the proposed graph growth has no demonstrated benefit.” If the dependency remains justified, record its exact API from official versioned documentation and add a focused test that would fail if the agent invented that API.
This is the dependency form of the phantom-convention problem described in How to Review AI-Generated Code: the agent reaches for a familiar public pattern even when the repository already has a local one.
PR 2: unexplained transitive churn
Review the manifest and lockfile separately. Confirm the direct requested range, the previous resolved version, the new resolved version, every parent path that materially changed, and the tool used to regenerate the lock. A test pass does not explain why 47 nodes changed. Require a reproducible diff produced from the intended edit.
PR 3: “development-only” execution
Inspect lifecycle scripts and workflow permissions before executing the package. A build tool can modify outputs or read credentials. Move the evaluation into a disposable environment with no production secrets, no publishing permission, and a network policy appropriate to the repository. If the task does not authorize execution, preserve the proposed diff as unverified and ask the authorized owner to run the documented check.
PR 4: conflicting license evidence
Stop. Do not average two license claims or ask the agent to choose the more permissive one. Record both sources, exact versions, and file paths, then route the conflict through the organization’s policy owner. Tests establish behavior, not permission.
PR 5: possible typosquat
Do not install the candidate to inspect it. Use registry metadata, source links, published archive inspection through an approved non-executing path, provenance, and namespace ownership. A copied README increases the need for identity proof. The safe outcome may be rejection without execution.
PR 6: false removal
“Removed from the manifest” and “absent from the resolved graph” are different states. Another direct component may still require the same package transitively. Separately check source imports, manifest intent, lockfile parent paths, bundled or packaged output, SBOM, and tests. The completion statement must match the strongest evidence available.
A review procedure for an AI-authored dependency PR
The sequence below is designed to stop cheap failures before expensive execution.
| Stage | Reviewer action | Stop condition | Output |
|---|---|---|---|
| 1. Scope | Compare task, changed files, and claimed outcome | Surprising files or unrelated dependency edits | Scope discrepancy list |
| 2. Necessity | Map every direct dependency to a call site and requirement | No demonstrated need or existing component is sufficient | Necessity note |
| 3. Identity | Verify exact ecosystem, name, namespace, source, and publisher | Identity mismatch or suspected typosquat | Identity record |
| 4. Resolution | Inspect manifest intent and lockfile graph | Missing resolution or unexplained churn | Direct and transitive diff |
| 5. Security | Query approved advisory sources for resolved versions | Affected version without accepted mitigation | Advisory record |
| 6. License | Match metadata, license text, SPDX expression, and policy | Missing, conflicting, or disallowed evidence | License record |
| 7. Maintenance | Review project stewardship and security practices | Risk exceeds repository policy | Maintenance note |
| 8. Build exposure | Inspect scripts, workflow permissions, and build-only tools | Unbounded execution or secret access | Build-input map |
| 9. Provenance | Verify attestation and artifact digest when applicable | Claim is unbound, invalid, or from an untrusted builder | Verification result |
| 10. Behavior | Run focused tests and end-to-end check in an approved environment | Requested behavior not proven | Test evidence |
| 11. Removal | Test whether the graph addition can be avoided or isolated | Simpler compliant solution exists | Keep, replace, or remove decision |
| 12. Completion | Reconcile every claim with recorded evidence | “Complete” exceeds what was verified | Accurate review summary |
At stage 1, use the same file-list discipline described in Debug Agent Instruction Conflicts and Write an AGENTS.md File for Coding Agents: explicit scope, approved commands, ownership, and completion evidence reduce the chance that a package operation becomes an unrelated refactor or release.
At stage 10, distinguish tests the agent wrote from independent tests. The author and its tests can share the same misunderstanding. Add at least one reviewer-selected assertion for the task’s most important boundary when risk warrants it.
For teams evaluating automated review products, AI Code Review Tools Compared explains where tool findings can help. Keep deterministic dependency-policy checks in machine gates, and do not replace accountable review with a second model’s prose.
Rejection conditions
Reject the pull request, or keep it explicitly unapproved, when any applicable condition below remains unresolved.
| Category | Reject when | What would reopen review |
|---|---|---|
| Scope | Dependency edit is unrelated to the stated requirement | Revised scope or removal of the edit |
| Necessity | No call site or measurable benefit supports a new direct component | Minimal design comparison and focused evidence |
| Identity | Package, publisher, source, or namespace cannot be matched | Primary-source identity chain |
| Typosquatting | Name similarity or metadata conflict remains unexplained | Verified intended package and clean provenance |
| Resolution | No exact deployed or built version can be determined | Lockfile, build graph, or equivalent resolution |
| Lockfile | Unrelated churn cannot be reproduced or explained | Repository-standard regeneration and reviewed diff |
| Vulnerability | Resolved version is affected and no accepted mitigation exists | Fixed version, removal, isolation, or approved exception |
| License | License is missing, contradictory, or outside approved policy | Reliable text and policy-owner decision |
| Maintenance | Ownership or release integrity changed without review | Verified transfer, release history, and risk acceptance |
| Build execution | Package scripts or tools receive excessive permissions | Sandbox and least-privilege workflow |
| Provenance | Artifact claim cannot be verified against the expected identity and digest | Valid attestation under an approved trust policy |
| Behavior | Focused and end-to-end evidence does not support the requirement | Corrected implementation and independent check |
| Removal | Equivalent existing code makes the package unnecessary | Smaller implementation or documented tradeoff |
| Completion | Summary claims more than the evidence proves | Precise statement of verified and unverified work |
Security scanners, SBOM exports, and attestations support these decisions; none grants blanket approval. GitHub’s artifact-attestation documentation explicitly says attestations do not guarantee security. OpenSSF Scorecard supplies signals rather than a universal verdict. SPDX standardizes records rather than issuing a legal compatibility decision.
When CI exists
Add deterministic checks to the pull request path without granting the agent broader authority:
- fail on manifest changes without corresponding lockfile review where the ecosystem uses one;
- produce a dependency diff showing direct and transitive additions, removals, and version changes;
- query approved known-vulnerability sources using exact resolved identities;
- enforce the organization’s license allow, review, and deny policy;
- flag new package lifecycle scripts and build-tool execution;
- produce or compare an SBOM when the release process supports one;
- verify artifact attestations against the expected repository, workflow, builder, and digest;
- run focused tests and the repository’s established verification suite;
- require a human owner for exceptions;
- retain machine-readable results with the reviewed commit.
Negative-test the gate. Feed it a fixture with a forbidden license, an affected version, a missing lockfile, an unexpected build script, and an invalid attestation. A check that has never been observed rejecting bad input is not yet trusted. Machine Gates for AI Output explains this fail-closed pattern in detail.
Keep package installation and build execution isolated from release credentials. GhostApproval: Which AI Coding Tools Were Affected? provides related context for why approval boundaries around tools matter, while Token Budgets and Circuit Breakers for AI Agents addresses runaway execution rather than dependency identity.
Manual review when there is no CI
No CI does not mean no process. It means the reviewer must create a dated evidence packet and avoid claiming automation that does not exist.
- Save the task text, changed-file list, and the contributor’s dependency rationale.
- Read the manifest diff without executing anything. List each direct addition, removal, requested range, feature, extra, scope, or environment marker.
- Read the lockfile diff as data. Count added, removed, and changed resolved nodes. Trace important transitive nodes to a direct parent.
- Verify package identity through official registry and linked source metadata. Check suspiciously similar names before any installation.
- Record license metadata and exact license-text location for the resolved version. Apply the organization’s policy; escalate ambiguity.
- Query approved advisory databases by ecosystem, exact name, and resolved version. Record the date and source.
- Review release history, security policy, maintainer changes, and relevant repository-security signals.
- Inspect package scripts and the project’s build configuration as text. Determine what would execute and what permissions it would receive.
- If an artifact and attestation already exist, verify their binding with an approved verifier and trust policy. Do not generate or upload artifacts merely to make the review look complete.
- Only when execution is authorized, use a disposable environment with no production secrets or publishing credentials. Follow the repository’s documented package-manager and test commands; do not substitute a remembered command.
- Exercise the changed behavior and add one reviewer-chosen check. Preserve command, environment, result, and limitations.
- Attempt the removal test: evaluate the smallest existing-library or platform alternative and compare the resulting graph and behavior.
- Write the verdict as “approved,” “rejected,” or “unverified,” followed by evidence and remaining risk. Do not use “complete” for checks that were not run.
| Manual evidence file | Contents | Freshness rule |
|---|---|---|
| Scope record | Task, changed files, authorized operations | Same proposed change |
| Graph record | Direct and transitive changes, parent paths | Same manifest and lockfile hashes |
| Advisory record | Source, time, exact identities, findings | Refresh before merge if graph or advisories changed |
| License record | Metadata, text location, SPDX expression, policy result | Same component version |
| Maintenance record | Repository, ownership, release and security signals | Recheck if release or owner changes |
| Build record | Scripts, permissions, builder, inputs, output digest | Same workflow and artifact |
| Test record | Commands, environment, outputs, skipped checks | Same reviewed commit |
| Decision record | Verdict, approver, exception, expiry if any | Superseded by a newer review |
This packet can later seed CI. Start with the facts that reviewers repeatedly collect rather than buying a broad scanner and assuming its default policy matches the repository.
SBOM, dependency graph, and attestation: what each can prove
| Artifact | Strong use | Important limit |
|---|---|---|
| Manifest | Shows declared direct intent and constraints | Does not necessarily show the exact resolved graph |
| Lockfile | Shows a resolver-selected graph and often integrity data | Does not establish necessity, license compatibility, or trusted production |
| Dependency graph | Supports path and impact analysis across known dependencies | Coverage depends on detection and submitted build-time data |
| SBOM | Portable inventory of components and relationships | Can be incomplete or stale; does not itself prove artifact origin |
| Vulnerability report | Maps known records to identified versions | Cannot cover undisclosed issues or fix identity errors |
| License report | Normalizes declared license data | Cannot make a context-specific legal decision |
| Provenance | Describes how an artifact was produced and its inputs | Value depends on completeness and trust in the builder |
| Artifact attestation | Binds a signed claim to a subject digest | A valid claim is not equivalent to secure or policy-compliant software |
| OpenSSF Scorecard | Surfaces selected repository security practices | Aggregate score is not an approval decision |
NIST defines an SBOM as a formal record of software components and supply-chain relationships and recommends connecting SBOM repositories with vulnerability detection for ongoing risk awareness. NIST also cautions that retroactively generated SBOMs may not reproduce the exact dependencies used at build time. Source: https://www.nist.gov/itl/executive-order-14028-improving-nations-cybersecurity/software-supply-chain-security-guidance-20
That caution is especially relevant to AI-generated changes. If the agent edited a manifest but did not preserve the resolver, environment, and build evidence, a later inventory may describe a plausible graph rather than the graph that produced the artifact.
The completion statement reviewers should require
A useful completion statement is bounded:
The reviewed diff adds one direct build dependency and six resolved transitive dependencies. Package identity, resolved versions, license metadata, known-advisory results, lifecycle scripts, and the focused behavior test were reviewed against the cited evidence. Artifact provenance was not available, so production origin remains unverified. No publish, deploy, or package installation was performed as part of this review.
That statement is stronger than “all good” because another reviewer can challenge each clause. If the agent invented an API, a versioned official reference and focused test can expose it. If it made extra changes, the file and graph inventory can expose them. If it claimed removal, the resolved graph and SBOM can test the claim. If it claimed security, the statement forces the narrower language of known-advisory coverage and provenance evidence.
Use Agent Session Handoff Artifact Guide when a dependency review spans sessions. The handoff should preserve the exact reviewed commit, evidence timestamps, unresolved decisions, and commands that still require an authorized environment.
Frequently asked questions
1. Is a lockfile enough to approve a dependency?
No. A lockfile can identify resolved versions and graph relationships, but it does not prove that the package is necessary, correctly licensed for the use, maintained, free from known issues, or built by a trusted process.
2. Is a direct dependency riskier than a transitive dependency?
Not by definition. A direct dependency is easier to see and justify. A transitive component can still execute at runtime or build time, carry a relevant license, or contain a known vulnerability. Review path and role rather than assuming one class is safe.
3. Why review both the manifest and the lockfile?
The manifest shows requested intent; the lockfile shows selected resolution. Comparing them reveals overly broad ranges, unexpected transitive changes, resolver drift, and changes unrelated to the task.
4. Does a clean vulnerability scan prove the package is secure?
No. It means the selected data source did not return a matching known record for the queried identity at the observation time, assuming the scan covered the file and ecosystem correctly.
5. Should a “dev dependency” receive less scrutiny?
Its runtime exposure may be lower, but its build exposure can be high. Review whether it executes, which inputs and secrets it can read, what it can write, and whether it influences released artifacts.
6. What if the agent added a package but never imported it?
Reject the addition unless another evidenced mechanism requires it, such as a configured plugin. An unused direct package expands the graph without supporting the task and may indicate a partial or misdirected implementation.
7. What if the import exists but the API is unfamiliar?
Check official documentation for the exact resolved version and add a focused test. Do not accept an agent-generated link, remembered method name, or code comment as proof that the interface exists.
8. How do I review a suspected typosquat without installing it?
Compare registry namespace, publisher, linked source, reciprocal source link, release history, package archive metadata through an approved non-executing method, and available provenance. Identity review should precede execution.
9. Does an SPDX identifier settle license compatibility?
No. It standardizes identification. Compatibility and obligations depend on the license expression, product, use, modification, linking, distribution, and organizational policy. Escalate cases outside the approved policy.
10. What if registry metadata and the repository license disagree?
Stop approval and record the conflict. Use reliable evidence for the exact version and obtain a policy-owner decision. Do not choose the more convenient statement.
11. Is OpenSSF Scorecard a pass or fail gate?
It can support a policy when individual checks and thresholds are deliberately chosen, but the aggregate score should not substitute for component identity, necessity, vulnerability, license, and build review.
12. What does an SBOM add beyond the lockfile?
An SBOM can provide a portable inventory with standardized package identifiers, relationships, versions, license fields, and other metadata across ecosystems and artifacts. Its value depends on coverage, freshness, and connection to the artifact.
13. Does a valid artifact attestation prove the code is safe?
No. It proves that a signed claim about a particular subject verifies under the selected trust policy. Reviewers must still assess the builder, source, workflow, inputs, code, dependencies, and policy.
14. What if no CI exists?
Use the manual evidence packet in this guide. Keep inspection and execution separate, record sources and dates, run authorized tests in a disposable environment, and label unrun checks as unverified.
15. Should reviewers allow an agent to regenerate the lockfile automatically?
Only when the task authorizes package operations and the agent uses the repository’s documented tool and version in an appropriate sandbox. Otherwise, request the regeneration as a separate authorized verification step.
16. How can I tell whether a dependency is removable?
Map its call sites, compare with existing utilities and platform features, isolate the wrapper, and run the same focused behavior tests without it. Include transitive graph reduction and maintenance cost in the comparison.
17. What if a vulnerable transitive dependency has no fixed version?
Evaluate whether the direct parent can be upgraded, configured, replaced, or removed; whether the affected path is reachable; and whether an approved isolation or exception process exists. Record an owner and review date for any exception.
18. Can an AI agent make the final license decision?
It can collect and normalize evidence under a defined policy. It should not invent missing terms or make context-specific legal conclusions outside that policy. Route ambiguity to the designated human or organizational owner.
19. Should the article’s process make a claim about AI-code copyright?
No. Preserve observable authorship and change records, third-party license evidence, prompts or task instructions where policy permits, human edits, and build provenance. A broad legal conclusion is outside this dependency review.
20. When is the dependency review complete?
When every applicable decision has evidence tied to the exact reviewed change, required checks have run in an authorized environment, unverified areas are named, and the verdict does not exceed that evidence.
Demand evidence for this guide
These primary sources demonstrate active institutional demand for dependency visibility, standardized inventories, repository security signals, and build provenance. They support the topic selection; they are not evidence that every repository needs every feature.
- GitHub provides dependency review specifically to show dependency changes and security impact in pull requests: https://docs.github.com/en/code-security/concepts/supply-chain-security/dependency-review
- NIST publishes software supply-chain guidance centered on SBOM transparency, provenance, and vulnerability response: https://www.nist.gov/itl/executive-order-14028-improving-nations-cybersecurity/software-supply-chain-security-guidance-20
- OpenSSF publishes package repository security principles covering authentication, provenance, vulnerability reporting, malware signals, and typosquatting defenses: https://repos.openssf.org/principles-for-package-repository-security.html
- SLSA maintains an industry-consensus specification for incrementally improving source and build supply-chain security: https://slsa.dev/spec/v1.2/
The editorial angle was also informed by an internal research memo summarizing user frustration with coding agents that make extra changes, invent interfaces, and overstate completion. Those qualitative complaints are used here only to choose review controls. Product facts in this article rely on the primary sources below.
Sources
Official and primary documentation checked on 2026-07-24:
- GitHub, supply-chain security overview, dependency graph, dependency review, Dependabot, and attestation concepts: https://docs.github.com/en/code-security/concepts/supply-chain-security/supply-chain-security
- GitHub, dependency graph concept: https://docs.github.com/en/code-security/concepts/supply-chain-security/dependency-graph
- GitHub, how the dependency graph recognizes manifest, lockfile, and submitted build-time data: https://docs.github.com/en/code-security/concepts/supply-chain-security/dependency-graph-data
- GitHub, dependency review and pull-request dependency diffs: https://docs.github.com/en/code-security/concepts/supply-chain-security/dependency-review
- GitHub, exporting an SPDX-compatible SBOM: https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/establish-provenance-and-integrity/export-dependencies-as-sbom
- GitHub, artifact attestations and provenance verification: https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations
- GitHub, dependency graph REST API surface: https://docs.github.com/en/rest/dependency-graph
- SPDX, project overview and standard purpose: https://spdx.dev/
- SPDX, current and previous specification versions: https://spdx.dev/use/specifications/
- SPDX, standardized license list and identifiers: https://spdx.org/licenses/
- OpenSSF, Scorecard project: https://openssf.org/scorecard/
- OpenSSF, principles for package repository security: https://repos.openssf.org/principles-for-package-repository-security.html
- OSV, vulnerability schema, database, and version-oriented query model: https://osv.dev/
- NIST, SBOM glossary definition: https://csrc.nist.gov/glossary/term/sbom
- NIST, software supply-chain and SBOM guidance: https://www.nist.gov/itl/executive-order-14028-improving-nations-cybersecurity/software-supply-chain-security-guidance-20
- SLSA, current Version 1.2 specification: https://slsa.dev/spec/v1.2/
- CycloneDX, Bill of Materials standard overview: https://cyclonedx.org/
- npm, package provenance display and verification prerequisites: https://docs.npmjs.com/viewing-package-provenance/
- npm,
package-lock.jsonpurpose and exact dependency tree: https://docs.npmjs.com/cli/v7/configuring-npm/package-lock-json/ - Python Packaging Authority,
pylock.tomlspecification: https://packaging.python.org/en/latest/specifications/pylock-toml/ - Python Packaging Authority, dependency specifiers and environment markers: https://packaging.python.org/en/latest/specifications/dependency-specifiers/
- Python Packaging Authority, dependency groups for development and internal uses: https://packaging.python.org/en/latest/specifications/dependency-groups/
- Rust Cargo Book, dependencies and lockfile updates: https://doc.rust-lang.org/cargo/guide/dependencies.html
- Rust Cargo Book,
Cargo.tomlversusCargo.lock: https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html - Go, modules reference for
go.mod,go.sum, graph selection, and authentication: https://go.dev/ref/mod - Apache Maven, transitive dependencies, scopes, and dependency management: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
- Microsoft NuGet,
PackageReferenceand dependency locking: https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files - Microsoft NuGet, package dependency resolution: https://learn.microsoft.com/en-us/nuget/concepts/dependency-resolution
- Microsoft NuGet, vulnerability information API: https://learn.microsoft.com/en-us/nuget/api/vulnerability-info
This article intentionally contains no affiliate links. It proposes no package installation, pull request creation, publication, deployment, or paid service.