Verify Dependencies Before Running AI-Generated Code

Check package identity, exact versions, installation behavior and operational ownership before accepting a dependency suggested by an AI coding assistant.

A plausible import is not a verified dependency

Before running AI-generated code, verify every newly introduced dependency against its intended project, exact release and installation behavior. A package that exists can still be the wrong package. A familiar project name does not establish who published the artifact, whether its API matches the generated code, or whether your build should execute its scripts.

Consider an illustrative change to a document-processing service. An assistant proposes a convenience package for converting uploaded files. The import looks reasonable and its description matches the task. The reviewer should first ask whether the existing implementation can satisfy the requirement, then investigate the proposed dependency without installing it into a privileged environment. This is a hypothetical review exercise, not a report of an Ampity customer incident.

The purpose is not to ban generated code or require a lengthy committee review for every small library. It is to separate a suggestion from an approved addition to the software supply chain. The depth of review should reflect what the package can access, where it executes and who will maintain it after the change ships.

Establish identity before evaluating popularity

Record the complete package identifier, including scope, registry and proposed version. Check it against the project's official documentation and release information reached independently of the assistant's answer. Similar spelling, a copied README or a large download count does not resolve an identity mismatch. If official instructions name a scoped package and the change installs an unscoped alternative, stop until the difference is explained.

The npm view documentation describes inspecting registry metadata and selecting particular versions. Use metadata as one piece of evidence, not as the publisher's independent endorsement. Inspect the exact release you intend to use rather than relying on information about the current default release.

Follow repository and documentation links, but do not assume that a declared repository URL proves the published archive was built from that repository. Where the ecosystem provides verifiable provenance or signatures, examine their scope and verification result. Where it does not, record that limit. A clean-looking project page cannot establish every step between source, build and distribution.

Keep unresolved identity separate from an ordinary compatibility problem. An incorrect API can be fixed by changing code. Uncertain publisher identity calls for a different package choice or a supply-chain investigation, not repeated installation attempts until the build turns green.

Decide whether the added dependency is necessary

Ask what requirement the package serves and what the application would lose without it. A new abstraction may save a few lines while introducing another release policy, license obligation, transitive tree and incident-response dependency. Existing platform capabilities or an already approved library may cover the need with less operational change.

For the hypothetical document converter, distinguish file detection, content extraction and rendering. A package that wraps all three may be convenient, but it may also execute external binaries or fetch supporting artifacts. The reviewer needs to understand the required behavior, not merely approve a broad label such as document support. Check resource bounds and unsupported formats as part of the decision.

Write down the rejected alternative as well. If the existing library cannot handle a required format, identify that limitation and the fixture demonstrating it. This makes the dependency decision reviewable later. Avoid introducing a general plugin framework solely because generated code imagined future integrations that the product does not yet need.

Ownership matters even for small packages. Name the team responsible for updates, advisory triage and replacement. If the dependency becomes unmaintained, the application still needs an exit path. Being open source does not mean someone else owns your production recovery.

Inspect execution boundaries before installing

Identify whether the package runs in the browser, build system, request handler, background worker or developer tooling. Review what credentials, files and network access exist in that environment. A development-only dependency can still execute in CI where repository tokens or deployment credentials are available. A production label alone does not capture the exposure.

Inspect lifecycle scripts and included executable files through an approved inspection workflow. If installation or compilation must execute scripts, use a disposable environment with restricted credentials and access appropriate to the task. Do not turn off a failing security control simply to reproduce the assistant's instructions. Record which behavior required execution and why.

Script suppression is useful for an initial investigation, but it is not a universal safe-install guarantee. It does not make later application execution harmless, and some legitimate packages need a build step before they work. Treat the inspection environment and the eventual runtime as separate boundaries with separate evidence.

Review new transitive dependencies and changes to existing resolutions. A one-line addition can alter a large tree. Unexpected registry hosts, remote downloads or unrelated package replacements need explanation. The relevant unit of review is the resulting artifact and dependency graph, not just the new line in the manifest.

Keep a small dependency acceptance record

Use a concise record tied to the pull request. The following fields are a proposed review aid, not an npm requirement or a claim of certification. They connect the addition to an actual product need and make unresolved questions visible.

| Question | Evidence to retain | Reason to hold the change | | --- | --- | --- | | Is this the intended project? | Full identifier, registry, official installation reference | Name or publisher cannot be reconciled | | Does this release implement the needed API? | Exact version and a representative behavior fixture | Generated call relies on an absent or different API | | What executes during installation and use? | Script inspection and runtime boundary | Unexpected privileged execution or network fetch | | What else changes in the tree? | Reviewed lockfile diff and transitive inventory | Unexplained resolution or registry changes | | Can the business use and maintain it? | License review and named update owner | Unresolved license or support obligation | | Can it be removed safely? | Replacement or rollback approach | Critical behavior has no understood recovery path |

['Is this the intended project?', 'Full identifier, registry, official installation reference', 'Name or publisher cannot be reconciled'], ['Does this release implement the needed API?', 'Exact version and a representative behavior fixture', 'Generated call relies on an absent or different API'], ['What executes during installation and use?', 'Script inspection and runtime boundary', 'Unexpected privileged execution or network fetch'], ['What else changes in the tree?', 'Reviewed lockfile diff and transitive inventory', 'Unexplained resolution or registry changes'], ['Can the business use and maintain it?', 'License review and named update owner', 'Unresolved license or support obligation'], ['Can it be removed safely?', 'Replacement or rollback approach', 'Critical behavior has no understood recovery path'], ].map(([question, evidence, hold]) => ( ))}

Do not treat every blank cell as permission to proceed. Mark unknowns explicitly and decide whether they are acceptable for the package's role. An unresolved license question or unexpected install script is not the same as a missing convenience benchmark. The owner should be able to explain why the remaining uncertainty is bounded.

Reproduce the reviewed tree, not a newer suggestion

After acceptance, preserve the reviewed dependency resolution. The npm ci documentation describes a frozen installation using an existing lockfile, with manifest and lockfile mismatches treated as errors. Matching installation configuration also matters. This establishes reproducibility of the declared tree, not that every item in it is trustworthy.

Review lockfile changes alongside the manifest and source changes. If the assistant solved a build failure by deleting the lockfile or broadening version ranges, require a reasoned replacement rather than accepting that as routine repair. Separate deliberate upgrades from the feature addition when doing so makes the change easier to evaluate and reverse.

Keep tool versions and relevant configuration in the acceptance evidence. A developer's successful local install and CI's install may differ because of flags, registry configuration or platform conditions. Confirm the actual build path that will produce the deployed artifact. Do not attach an old successful job to a newly changed lockfile.

Reproducibility also has limits. Native artifacts and platform-dependent branches need testing on the supported targets. A deterministic dependency resolution does not demonstrate that the document converter behaves correctly for an oversized file, a malformed input or the deployment platform's available binaries.

Use vulnerability reports without mistaking them for approval

The npm audit documentation describes checking dependency information against known vulnerability reports. It also explains that audit fixes can perform installation changes. Review proposed fixes as dependency changes, including compatibility and lockfile effects, rather than treating automatic remediation as consequence-free.

A report with no known findings is not proof that a package cannot be malicious, that its license is suitable, or that the generated code uses it correctly. Those are different questions. Conversely, a finding needs interpretation in the actual execution context, a documented response and an owner. Dismissing it because the package is only used during builds can miss a privileged execution path.

Check what metadata the auditing process sends and use an approved registry or advisory service for your environment. Avoid exposing private dependency names through an improvised external workflow. Capture the result, reviewed tree and decision without copying secrets or proprietary code into the record.

Do not promise that a scanner score predicts all future risk. Decide how new advisories reach the owner and how an urgent replacement would be tested. A review completed once does not eliminate the maintenance obligation created by adding the package.

Test the dependency through the product boundary

For the example converter, test actual supported formats, rejected formats, size limits, timeouts and failure cleanup. Confirm that invalid files do not become success responses with empty content. Check whether generated code calls an API that changed between releases or catches every exception and hides a conversion failure.

Use test inputs created for the review, with no customer data. Inspect the produced output and resource behavior as well as the function's return value. A mocked library response can test the wrapper, but it cannot verify how the real package handles files. Keep the distinction clear in the evidence.

Finally, decide whether the addition is accepted, replaced or held. Keep identity, installation, behavior and maintenance evidence together so the decision survives the original author leaving the team. For the related question of whether generated tests actually prove the change works, read code review evidence when AI wrote the change. If the wider technology choice needs review, start with technology stack evaluation and a concrete requirement rather than a package wishlist.