Safeguard
Supply Chain Security•

Should an AI Coding Agent Upgrade Your Dependencies on Its Own?

Only within limits. Let agents propose patch and minor upgrades behind tests and a release age delay; keep majors, overrides and lockfile rewrites human.

Safeguard Security Team
36 min read

Not without limits. An AI coding agent can safely propose dependency upgrades, and for patch releases with passing tests it can do most of the work, but it should not choose versions, rewrite lockfiles and merge on its own authority. Give it a written autonomy policy, a release age delay, a test gate and a human approval step for anything major.

"Upgrade the dependency" sounds like one action and is really several: choosing a target version, deciding where in the manifest to express it, letting the package manager resolve the tree, running install scripts, and proving nothing broke. A coding agent can do all of them. The question for a tech lead is which ones you are comfortable having done without a person looking, and what evidence you want attached when a person does look.

Key takeaways

  • An agent asked to "fix the vulnerability" can bump a direct dependency, add an override or resolution, regenerate the lockfile, or rewrite code to drop the package. Each has a different blast radius, and you should know which one it chose before you merge.
  • The right target is usually the lowest release that contains the fix, on the same major line, not the newest release on the registry.
  • Brand new releases carry extra risk. Package managers now ship release age controls (min-release-age in npm, minimumReleaseAge in pnpm, exclude-newer in uv) that make "wait a few days" enforceable rather than a habit.
  • Overrides and resolutions are powerful and silent. They apply across the whole tree and outlive the reason they were added, so treat them as a change that always needs a human.
  • A safe policy is tiered: patch upgrades with green tests can be proposed and even merged by automation, minor upgrades need tests plus a reviewer, majors and overrides need an owner's approval.
  • Agent permissions are configurable in the agents themselves. Use those controls so install, publish and push commands always ask.
  • Purpose built remediation, such as Safeguard's Griffin fix pull requests, starts from the advisory and a version strategy instead of a free form prompt, and Safeguard ships it switched off with every category set to Manual so you choose how much runs on its own.

Why this question is coming up now

Two things are pushing teams to decide.

The first is adoption. An Ask HN thread this autumn, "Is anybody producing good code with coding agents?", captures the mood: the poster found agent merge requests far slower to review, and commenters with good results described small changes, specs up front, and tests and linters as guardrails. Dependency changes are where review bites hardest, because a two line diff to package.json can pull in code nobody on the team wrote.

The second is the threat picture. A threat research report summarized by SecurityBrief Asia on 22 October 2026 counted 215 actively exploited vulnerabilities in the first half of 2026, up 34% on the same period a year earlier, and described attackers using compromised maintainer accounts and package lifecycle scripts to steal credentials from developer and CI environments. One example it describes involved npm packages that added malicious preinstall behaviour, so simply running npm install was enough to execute the payload. When an agent runs installs unattended, it inherits exactly that exposure.

Agents already touch dependencies; the question is how much they may do without a person in the loop. Whether agents introduce vulnerable packages in the first place is covered in do AI coding agents add vulnerable dependencies.

What agents actually do when asked to "fix the vulnerability"

Give a coding agent a scanner finding and the instruction "fix it," and which move it picks depends on the ecosystem, the tree, the advisory and the wording of the prompt. These are the common ones.

Move 1: Bump the direct dependency

If the vulnerable package is something you depend on directly, the obvious fix is to raise the version in the manifest and reinstall. In npm that is an edit to package.json followed by npm install. In Go it is go get example.com/pkg@v1.2.3, which the Go modules reference describes as adding or changing the require directive so the module stays at that version. In Python it is an edit to pyproject.toml or requirements.txt and a fresh lock.

This is the cleanest fix, as long as the target is sensible. The Go reference notes one subtlety that holds everywhere: if the new version requires a higher version of another module, that module is upgraded too. A one line manifest change can move several packages.

Move 2: Run the ecosystem's automatic fixer

Agents often reach for the package manager's own audit fixer. npm's documentation describes npm audit fix as scanning the project and applying remediations to the package tree, and notes that it runs a full npm install underneath. The important flag is --force. According to the npm docs, --force lets audit fix install modules outside your stated dependency range, including semver major changes, and npm strongly advises against using it unless you understand the consequences.

An agent that hits "some vulnerabilities require manual review" and retries with --force has just made major version decisions across many packages in one command. A permission rule, covered below, prevents it.

Move 3: Add an override or resolution

When the vulnerable package is transitive, deep in the tree under something you do not control, the direct bump does not work. The agent will often add an override instead. npm's overrides field, Yarn's resolutions field and pnpm's equivalent all let you force a version of a package anywhere in the tree. npm's docs list patching a dependency with a known security issue as a use case for exactly this.

Overrides fix the finding immediately. They also replace a version the library author tested against with one they did not, and they outlive the reason they were added.

Move 4: Regenerate the lockfile

Sometimes the agent deletes the lockfile and reinstalls, or runs a broad update, because every range then floats to its newest match and the finding disappears. So do your chances of reviewing the diff, since hundreds of unrelated packages move.

Move 5: Rewrite code to remove or replace the package

Less often, an agent replaces a small library with hand written code or a different package. That can be fine for a trivial utility. It can also swap a well known package for an obscure one, or reimplement parsing badly. A different package is a new dependency decision and should be reviewed as one.

Which move is safest

MoveTypical diffBlast radiusEasy to review?Human approval?
Bump direct dependency, same majorManifest line plus lockfile entries for that packageLowYesOptional for patch, yes for minor
Bump direct dependency, new majorManifest plus code changes for breaking APIMedium to highPartlyAlways
Audit fixer without forceLockfile only, within rangesLow to mediumMostlyOptional with green tests
Audit fixer with forceManifest and lockfile, can cross majorsHighNoAlways, and better to block
Override or resolutionOne root manifest entry, tree wide effectMedium, hiddenDeceptively easyAlways
Full lockfile regenerationHundreds of linesHighNoAlways, and better to block
Replace the package or rewrite codeNew dependency or new codeVariesNeeds a design reviewAlways

The pattern is simple. The smaller and more explicit the change, the more automation it can tolerate.

Do agents pick the newest version, the fixed version, or something in between?

It depends on how they are asked. Left alone, general agents tend to lean toward "latest," because "upgrade to the latest version" is the most common advice in documentation and issue threads. Some read the advisory and pick the first fixed version. Some accept whatever the resolver picks.

For security fixes, the right default is the lowest version that contains the fix, on the major line you are already using. Here is why:

  • It is the smallest behaviour change. Under Semantic Versioning, a patch release should contain only backward compatible bug fixes, and a minor release adds backward compatible functionality. The further you jump, the more unrelated changes ride along.
  • It is the version the advisory was written about. Advisories list affected ranges and fixed versions. The first fixed version is the one most likely to have been checked against the report.
  • It has usually been out longer. A fix released last month has had a month of other people installing it. The newest release may be hours old.

Two exceptions. If the first fixed version has its own later advisory, you want the lowest version that clears all of them. And if the fix is on an unmaintained line, moving to a supported line may be better, as a human decision.

Go makes this easier to reason about than most ecosystems. The Go modules reference explains that minimal version selection never picks a version just because it is newest: the build list is made of the minimum versions that satisfy every requirement, and newer releases do not change it unless a go.mod asks for them. The reference also documents go get -u=patch, which upgrades named dependencies only to their latest patch release on the same minor line. Other ecosystems need you to express the same discipline in policy.

A useful instruction to put in your agent's project memory or rules file is short and specific:

When fixing a vulnerable dependency:
- Target the lowest version that fixes every listed advisory, on the current major line.
- Do not run npm audit fix --force, npm update without a package name, or delete lockfiles.
- Do not add overrides or resolutions without asking.
- State the old version, new version, advisory IDs and why this version was chosen in the PR body.

Agents follow written project instructions far more reliably than they follow unstated preferences.

Major version bumps and breaking changes: who checks?

Semantic Versioning is precise on this point. The spec says the major version must be incremented when backward incompatible changes are introduced to the public API, and that during initial development, under version 0.y.z, anything may change at any time. So a major bump is a declared promise that something broke, and a 0.x bump of any kind offers no promise at all.

Agents can handle majors, sometimes well: they read changelogs, update imports and adjust configuration. In Go the change is even visible in the import path, since modules at v2 and above carry a /v2 style suffix. The problem is not capability. A major upgrade is a design decision with consequences outside the diff:

  • Runtime behaviour your tests do not cover. Default timeouts, retry behaviour, serialization formats, logging output and error types change in majors. Tests rarely assert on all of them.
  • Peer and plugin compatibility. A framework major can strand plugins that have not caught up.
  • Operational changes. New minimum runtime versions, new native build requirements, different environment variables.
  • Data compatibility. Anything that persists data, from ORMs to caching libraries, can change formats across a major.

So the answer to "who checks?" should be: a named human owner of that part of the codebase, with the agent's analysis as input. GitHub's CODEOWNERS file is a practical way to make that automatic. GitHub's docs explain that owners are requested for review when a pull request touches files they own, and that enabling "Require review from Code Owners" in a branch protection rule or ruleset makes that approval mandatory. Assign your manifests and lockfiles to the platform team or the service owner, and a major bump cannot merge without them.

# .github/CODEOWNERS
/package.json         @your-org/platform
/package-lock.json    @your-org/platform
/pnpm-lock.yaml       @your-org/platform
**/go.mod             @your-org/platform
**/pyproject.toml     @your-org/platform
**/uv.lock            @your-org/platform
/.github/CODEOWNERS   @your-org/platform

GitHub's docs also recommend giving the CODEOWNERS file itself an owner, so the rule cannot be quietly removed in the same pull request.

Why a brand new release is riskier than one that has been out for days

Every release goes through a period where it has been published but not yet widely installed. During that window, three kinds of problems tend to surface:

  1. Plain regressions. A release breaks something the maintainers did not test. Early adopters hit it, report it, and a follow up release appears within hours or days.
  2. Bad packaging. Missing files, wrong build artifacts, broken type definitions. Usually caught fast and fixed fast.
  3. Compromised publishes. When a maintainer account is taken over, the malicious version is often found and pulled after it has been live for a short time. The report summarized by SecurityBrief Asia describes exactly this pattern of compromised maintainer accounts and install scripts in 2026 campaigns.

A short delay costs little and sidesteps much of all three. Package managers now let you enforce it.

  • npm. The npm config docs describe before, which restricts installs to versions published on or before a given date, and min-release-age, which takes a number of days and installs only versions that were available more than that many days ago. If both are set in the same place, before wins.
  • pnpm. pnpm's dependency resolution settings document minimumReleaseAge, measured in minutes, which delays installing newly published versions and applies to transitive dependencies as well. The docs list the default as 1440 minutes, one day, from pnpm 11, and zero before that. minimumReleaseAgeExclude lets you exempt specific packages or scopes, for example your own internal packages. pnpm also documents a trustPolicy setting that, when set to no-downgrade, fails an install if a package's trust level is lower than in its earlier releases.
  • uv. uv's settings reference documents exclude-newer, which limits candidates to distributions uploaded before a cutoff. It accepts a timestamp or a duration such as 7 days, and exclude-newer-package can set or lift the cutoff for individual packages.

Here is what that looks like in configuration:

# .npmrc
min-release-age=3
ignore-scripts=true
# pnpm-workspace.yaml
minimumReleaseAge: 4320   # three days, in minutes
minimumReleaseAgeExclude:
  - "@your-org/*"
# pyproject.toml
[tool.uv]
exclude-newer = "3 days"

On ignore-scripts: npm's config docs say that when it is true, npm does not run scripts defined in package.json files, though explicit commands such as npm test still run their target. That blocks install time lifecycle scripts at the cost of breaking packages that need a build step, so many teams enable it in CI and agent sandboxes with a few exceptions.

The security fix exception

A release age delay is a default, not a law. When a vulnerability is being actively exploited, waiting three days for a fix can be the wrong trade. The sensible policy is:

  • Keep the delay on for routine upgrades and for anything the agent proposes on its own initiative.
  • For a fix to a known exploited vulnerability, allow a human to exempt the specific package and version, record why, and remove the exemption afterwards.
  • Never let the agent grant itself the exemption.

That last point matters. An agent told to fix a vulnerability may well find the setting blocking the install and change it.

Lockfiles, overrides and resolutions: where agents get this wrong

The manifest says what you want. The lockfile records what you got. Most agent mistakes with dependencies live in the gap between the two.

Lockfile mistakes

  • Deleting and regenerating. As covered above, this makes findings disappear and makes the diff unreviewable. Block it.
  • Editing the lockfile by hand. Some agents will try to change a version string directly in package-lock.json or poetry.lock. The integrity hashes and resolved URLs then no longer match, and the next install either fails or silently rewrites the entry. The lockfile should only change through the package manager.
  • Updating the manifest but not the lockfile. The pull request looks right, CI installs from the old lockfile, and the vulnerable version ships anyway. Using npm ci in CI, which fails when the manifest and lockfile disagree, catches this.
  • Running a broad update command. npm update with no package name, poetry update with no package name, or go get -u ./... all move far more than the vulnerable package. The narrow forms exist for a reason.
  • Using a different package manager version. Lockfile formats change between major versions of package managers. An agent running a newer local tool can rewrite the whole file format in passing. Pin the package manager version in the repository.

npm's audit docs describe --dry-run, which reports what npm would do without changing anything, and --package-lock-only, which updates only the lockfile. An agent can attach npm audit fix --dry-run --json output to the pull request, turning a guess into a plan.

Override and resolution mistakes

Overrides are where general agents most often make a change that looks small and is not.

npm's docs describe a shorthand that forces one version everywhere, an object form for a package and its children, and parent scoped forms that apply only under a specific parent. Two documented constraints trip agents up:

  • If you depend on a package directly, an override for it must use exactly the same spec as your dependency, or npm throws an EOVERRIDE error. The $ prefix, as in "foo": "$foo", reuses the direct dependency's spec.
  • Overrides are only read from the root package.json. An override added in a workspace package or a dependency is ignored.

Yarn's manifest docs describe the equivalent resolutions field, which can pin a package everywhere or only under a specific parent path, and note that it can only be set at the root of the project.

The common agent errors:

  1. Global override when a scoped one would do. Forcing "minimist": "1.2.8" everywhere instead of only under the parent that pulled in the vulnerable version. The global form can move unrelated copies of the package.
  2. Override that crosses a major. Forcing a transitive package onto a new major that its parent was never tested with. Tests may still pass if your code never reaches that path. Production may not be so lucky.
  3. Override in the wrong file. Added in a workspace package, so it does nothing, and the scanner finding persists while the pull request description says it is fixed.
  4. Override that never gets removed. Months later the parent package ships a release that depends on the fixed version natively, and the override is now pinning you to an old patch. Nobody remembers why it is there.

Require every override to have a record, in a DEPENDENCY_OVERRIDES.md or the pull request that added it, naming the advisory, the parent package and the removal condition. JSON has no comments, so the record has to live elsewhere.

Here is a well formed, narrowly scoped npm override for comparison:

{
  "dependencies": {
    "some-cli-tool": "^4.2.0"
  },
  "overrides": {
    "some-cli-tool": {
      "minimist": "1.2.8"
    }
  }
}

It moves only the copy of minimist under some-cli-tool, it names an exact fixed version, and it lives in the root manifest. If your agent produces something broader than this, ask why.

What a safe autonomy policy looks like

Write the policy down where people and agents can read it, then enforce it in tools. A tiered policy works well.

Change typeWho may proposeWho may approveRequired checksMerge
Patch upgrade, direct dependency, same major and minorAgent or remediation toolAutomation, if all checks passFull test suite, release age met, no new advisories, lockfile changed only for the target package and its required dependenciesAutomatic merge allowed for low risk repos
Minor upgrade, same majorAgent or remediation toolOne reviewerAbove, plus changelog link in PR bodyManual
Major upgradeAgent may prepareCode ownerAbove, plus migration notes and owner sign offManual
Override or resolutionAgent may prepareCode ownerAdvisory ID, parent package, removal condition recordedManual
New dependency or package replacementAgent may suggestCode owner and securityPackage review, license checkManual
Release age exemptionHuman onlySecurity leadKnown exploited status recordedManual
Lockfile regenerationHuman onlyCode ownerJustificationManual

Three principles sit underneath the table.

Tie autonomy to reversibility. A patch upgrade in a service with good tests and a fast rollback is cheap to undo. A major upgrade in a library that writes data to disk is not. If you have not tested your rollback path, our post on whether your rollback is ready before auto merge is the place to start.

Separate proposing from merging. Opening a pull request costs almost nothing; merging is the decision that matters.

Enforce at the boundary, not in the prompt. A rules file helps, but a different agent will not read it. Branch protection, CODEOWNERS, required checks and policy gates apply whoever opened the pull request.

For more on what must pass before any automated merge, see auto merge for security PRs: what must pass first, and for the specific question of merging AI written fixes, should AI written fix PRs ever auto merge.

Configure the agent itself

The agent's own permission system is the first layer, and the major coding agents document theirs.

Claude Code. Anthropic's permissions documentation describes permission rules that allow, ask for or deny specific tools and commands, evaluated in a fixed order: deny first, then ask, then allow, with the first match deciding. Rule specificity does not change that order, so a broad deny beats a narrow allow. Rules can live in a project's .claude/settings.json, in user settings, or in managed settings that administrators deploy and that other levels cannot override. The docs also describe permission modes, including the default mode (labelled Manual), which prompts on first use of each tool, plan, which explores without editing source files, and bypassPermissions, which the docs say to use only in isolated environments such as containers or VMs. Administrators can disable bypass and auto modes through settings.

A project settings file that keeps dependency changes under human control might look like this:

{
  "permissions": {
    "allow": [
      "Bash(npm test *)",
      "Bash(npm run lint *)",
      "Bash(npm audit --json)",
      "Bash(npm ls *)"
    ],
    "ask": [
      "Bash(npm install *)",
      "Bash(npm ci *)",
      "Bash(npm audit fix *)",
      "Edit(package.json)",
      "Edit(package-lock.json)"
    ],
    "deny": [
      "Bash(npm audit fix --force *)",
      "Bash(npm publish *)",
      "Bash(rm package-lock.json)",
      "Bash(git push *)"
    ]
  }
}

Check the rule syntax against the current docs, since matching details change between releases. The principle holds: reads and tests run freely, installs and manifest edits ask, force fixes, publishes and pushes are denied.

OpenAI Codex. OpenAI's Codex sandboxing documentation describes sandbox modes, read-only, workspace-write and danger-full-access, and approval policies including on-request, where the agent works inside the sandbox and asks when it needs to go beyond it, and never, where it does not stop for approval prompts. The docs describe danger-full-access as removing both filesystem and network boundaries. For dependency work, the combination that keeps a person in the loop is a sandboxed mode with an approval policy that asks, because an install reaches the network.

Safeguard CLI. The CLI's assistant can edit code and run commands, and /permissions switches between Ask, Accept edits, Plan, Auto (the default) and Strict. For dependency work, Ask or Strict keeps every install and edit behind your approval, and the desktop and phone apps can approve each command remotely.

Configure CI as the backstop

Whatever the agent does locally, CI is where the policy becomes non negotiable. A minimal GitHub Actions job for dependency pull requests:

name: dependency-checks
on:
  pull_request:
    paths:
      - "package.json"
      - "package-lock.json"

jobs:
  verify:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - name: Install exactly what the lockfile says, no lifecycle scripts
        run: npm ci --ignore-scripts
      - name: Run tests
        run: npm test
      - name: Fail on high or critical advisories
        run: npm audit --audit-level=high
      - name: Show what changed in the tree
        run: git diff --stat origin/${{ github.base_ref }} -- package-lock.json

Mark the job as a required check. The git diff --stat step is not a gate, but it shows the reviewer at once whether the lockfile changed by ten lines or ten thousand.

How to review an agent's dependency PR in five minutes

This checklist fits in five minutes for a typical patch or minor upgrade. Majors take longer, by design.

Minute one: what changed in the manifest. Open the manifest diff first. Confirm it touches only the package named in the pull request title. Check the version jump: patch, minor or major? Check for new overrides, resolutions or equivalent fields. If any appeared and the pull request title does not say so, stop and ask.

Minute two: how big is the lockfile diff. You are not reading the lockfile line by line. You are checking its size and shape. For npm, a patch upgrade of one package normally changes a handful of entries. If the lockfile diff is enormous, the agent probably regenerated it or ran a broad update. Ask for a narrow redo.

git diff --stat main -- package-lock.json
npm ls minimist --all

Minute three: is the target version the right one. Look up the advisory. Is the new version the first fixed version on your major line, or something later? If later, the pull request body should say why. Check the publish date. If the version is a few hours old and this is not an emergency, it should wait for your release age window. A free lookup in Gold Open Source shows affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version without a login, which is often the fastest way to confirm.

Minute four: did the evidence come with it. The pull request body should state the old and new versions, the advisory IDs, why this version was chosen, and what the agent ran to verify it. CI should be green, and the tests that ran should actually exercise the package. If the only test run was a lint, the change is untested.

Minute five: what else did the agent touch. Scan the file list. Agents sometimes "helpfully" fix a failing test by changing the test, update a CI config to make a check pass, or edit a release age setting that blocked the install. Any change to tests, CI configuration, package manager configuration or permission files in a dependency pull request deserves a hard look.

If all five pass, merge. If not, send it back with a specific instruction such as "redo this as a scoped override under some-cli-tool only."

Bot updates vs agent updates vs purpose built fix PRs

Three kinds of automation can open a dependency pull request, and they behave differently enough that it is worth being clear about which you are dealing with.

Rule based update bots. These open pull requests when new versions appear or an advisory matches. They are predictable and good at volume. They do not read your code, and they generally do not adapt it to a breaking API. Our post on whether to turn on auto merge for dependency update bots covers that category in detail.

General purpose coding agents. These can do anything a developer can do in a terminal, including updating call sites for breaking changes. They are also non deterministic, sensitive to prompt wording and prone to force fixes, broad updates and global overrides.

Purpose built remediation. This starts from a specific finding and a defined strategy. The version choice follows a stated rule, the change is scoped, and the result is checked before the pull request opens.

QuestionUpdate botGeneral coding agentPurpose built fix PR
What starts it?New version or advisoryA person's promptA specific finding
How is the target version chosen?Configured rulesWhatever the agent decidesA defined strategy
Can it adapt code to breaking changes?Generally noYesDepends on the tool and strategy
Deterministic?YesNoMore constrained than an agent
Explains the change?Basic notesOften, if askedAs part of the PR
Scope controlConfig filePrompt and permissionsCategory and strategy settings
Best used forRoutine version freshnessComplex migrations with a human drivingSecurity fixes at scale with policy

Many teams use all three: a bot for freshness, remediation for vulnerability fixes, and an agent with a person driving for hard majors.

Where Safeguard fits

Safeguard's autonomous remediation is the purpose built category, and it is generally available. When a vulnerability has a fixed version, Griffin, Safeguard's remediation model family, works through analysis, a proposed solution, an impact assessment, pull request creation and validation, and opens a tested fix pull request. It includes breaking change detection and covers JavaScript, Python, Java, Go, Rust, Ruby, .NET and PHP. You can run it on one repository or in bulk, with one pull request per repository.

For vulnerability and dependency fixes, you choose a strategy rather than writing a prompt:

  • Safest: backward compatible fixes only.
  • Balanced: minor version updates and patches, with minimal breaking changes.
  • Aggressive: all available fixes, including major version updates.
  • Smart: the model chooses per item based on context, risk and impact.

Those strategies map cleanly onto the tiered policy above. A team can run Vulnerabilities on Safest with automatic pull requests, keep Dependencies on Manual, and save Aggressive for a quarter where someone is assigned to handle the majors.

Autonomous remediation ships switched off, with every category set to Manual, and nothing is applied until an administrator turns on the master toggle. How much autonomy you grant should be a decision, not an accident of installation.

Pull requests are the proposal half; policies and gates are the enforcement half. Policies generate findings, and gates evaluate them at checkpoints such as CI and release, where a gate can block, warn, notify or require approval. So "majors need an owner's approval" holds whether a bot, an agent, Griffin or a person opened the pull request. Reachability analysis ranks findings in code paths your application actually calls, which helps decide which fix pull requests to review first.

Two limits. A fix pull request is only as safe as the tests it runs against. And Safeguard's role here is version choice, validation and policy, not vetting a newly published package, so keep the release age settings in your package manager configuration.

Common mistakes

  1. Treating install permission as harmless. npm install and pip install can execute code from the internet.
  2. Letting the agent edit its own guardrails. If the agent can change .npmrc, pnpm-workspace.yaml, CI workflows or its own settings file, it can remove the release age delay or a required check to get an install through. Put those files under CODEOWNERS and ask rules.
  3. Accepting "latest" as the target. The newest release is the least tested one. For security fixes, the first fixed version on your major line is almost always the better choice.
  4. Allowing npm audit fix --force. It can cross major versions across many packages at once. Deny it at the agent level and catch it in review.
  5. Trusting a green CI run that never exercised the package. Passing tests prove nothing if none reach it.
  6. Adding overrides with no exit plan. Every override should record the advisory, the parent package and when to remove it. Unrecorded overrides become permanent pins.
  7. Reviewing the code diff and skipping the lockfile size. The lockfile tells you whether the change was narrow. Check its size every time.
  8. One policy for every repository. A prototype and a payments service should not share an autonomy level.
  9. Different agents, different rules. Per agent rules diverge across teams. Enforce the policy at the repository and CI level so it holds for every tool.
  10. Merging a fix and never checking that the vulnerable version is gone. Confirm with npm ls lodash --all, go list -m all or uv tree, and keep a CI check that fails if the version comes back.

Fix it without waiting for upstream

Everything above assumes a fixed version exists and the only question is who applies it and how. The harder gaps are the time it takes to get a fix into every repository, and the time before a fix exists at all.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

FAQ

Is it safe to let an AI agent run npm install?

Only with care. npm install downloads code and, unless scripts are disabled, runs package lifecycle scripts on the machine. Run agents in a sandbox or container, set ignore-scripts=true where you can, use a release age delay, and configure the agent so install commands ask for approval rather than running freely.

Should an AI agent update dependencies to the latest version?

Usually not for security fixes. The lowest version that fixes every relevant advisory on your current major line is the smaller, better tested change. Move to the latest version as a deliberate, separately reviewed upgrade.

Can an AI coding agent handle major version upgrades?

It can prepare them, often well, by reading changelogs and updating call sites. A person who owns that code should still approve, because majors change behaviour in ways tests may not cover. Make that approval mandatory with CODEOWNERS and a required review.

What is a minimum release age and should I use one?

It is a package manager setting that refuses versions published more recently than a set window. npm calls it min-release-age (days), pnpm calls it minimumReleaseAge (minutes), and uv uses exclude-newer with a duration. A few days is a common choice, with a documented human exemption for urgent security fixes.

Why do agents use npm overrides to fix vulnerabilities?

Because the vulnerable package is often a transitive dependency the project does not list directly, and an override is the fastest way to force a different version. Overrides apply tree wide, only work in the root package.json, and persist until removed, so they should always get a human review.

How do I stop an AI agent from running npm audit fix --force?

Deny the command in the agent's permission settings. In Claude Code, a deny rule is evaluated before any allow rule, so a deny for the force form blocks it even if broader npm commands are allowed. Back it up with a CI check and with CODEOWNERS on the manifest and lockfile.

Should AI generated dependency PRs be auto merged?

Only for the lowest risk tier: patch upgrades on the same minor line, with a full test suite passing, the release age met and no new advisories, in a repository with a tested rollback. Everything else should wait for a person.

Does Safeguard's remediation merge pull requests on its own?

Safeguard's autonomous remediation opens tested fix pull requests and ships switched off, with every category set to Manual. Your team decides which categories run automatically and which strategy each uses, and Safeguard's policy gates can require approval or block a merge at CI or release.

See how Safeguard would help

This first demo shows the Safeguard CLI fixing a lodash vulnerability. It reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing. It then shows /permissions, /model and /scan ., which is where you would choose a stricter mode for dependency work.

Click through it at your own pace, or open it full screen.

The second demo is a real Android session that sends work to a computer running the CLI and approves the command on the phone with Allow once, Allow for turn or Deny. For dependency upgrades, that means the person who owns the decision can approve an install without being at the machine where the agent runs.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and chooses which tools Claude can use. The same idea applies to dependency work: decide up front which actions an agent may take, and leave the rest out.

Click through it at your own pace, or open it full screen.

To try it on your own repositories, download Safeguard or read the CLI documentation. For how the CLI's assistant approaches security fixes, see the Safeguard CLI as a security aware coding assistant.

Quick check

An agent fixes a transitive vulnerability by adding a global npm override that moves a package up one major version, and all tests pass. Should it merge?

No, not without an owner's review. The override applies across the whole tree, crosses a major version the parent package was never tested with, and passing tests only prove the paths your tests reach. Ask for a parent scoped override to the first fixed version on the current major line, with the advisory and removal condition recorded.

Your pnpm settings enforce a three day minimum release age, and the only fix for an actively exploited vulnerability was published this morning. What should happen?

A person, not the agent, adds a specific exemption for that package and version with minimumReleaseAgeExclude, records why, and removes it once the window has passed. The delay stays in force for everything else.

Sources

Last reviewed: 23 October 2026. Package manager and coding agent settings change between releases; check the linked documentation for current behaviour.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.