Product

Safeguard Auto-Fix: Automated Vulnerability Remediation That Respects Your Codebase

Auto-Fix generates pull requests that update vulnerable dependencies with compatibility checks, test validation, and rollback safety. Remediation at the speed of disclosure.

Bob
Security Researcher
6 min read

Finding vulnerabilities is the easy part. Fixing them is where the wheels come off.

The average time to remediate a known vulnerability in open-source dependencies is 271 days, according to industry data. Not because organizations do not know about the vulnerabilities -- their SCA tools told them months ago. But because updating dependencies is manual, risky, and competes for attention with feature work.

Safeguard Auto-Fix automates the remediation workflow: detecting the fix, generating the update, validating compatibility, and opening a pull request. Your developers review and merge instead of researching and implementing.

Why Remediation Is Slow

The manual remediation workflow for a single vulnerable dependency looks like this:

  1. Receive the vulnerability alert
  2. Identify which component is affected and which projects use it
  3. Determine which version fixes the vulnerability
  4. Check if the fix version is compatible with your code
  5. Update the dependency in your manifest
  6. Run tests to check for regressions
  7. Open a pull request
  8. Get code review
  9. Merge and deploy

Steps 1 through 6 take anywhere from 30 minutes to several hours per vulnerability, depending on the complexity of the update. For transitive dependencies, add another step: figure out which direct dependency pulls in the vulnerable transitive, and update that instead.

Now multiply by the 30 to 50 vulnerabilities in a typical enterprise project at any given time, and you understand why remediation backlogs grow faster than teams can work through them.

How Auto-Fix Works

Auto-Fix operates in four phases.

Phase 1: Fix Identification

When Safeguard SCA identifies a vulnerability in a component, Auto-Fix checks whether a fix exists. This means finding a version of the affected component that:

  • Addresses the specific CVE
  • Is a stable release (not a release candidate or beta)
  • Is within a reasonable upgrade path from the current version

"Reasonable upgrade path" is key. Jumping from Jackson-databind 2.9.8 to 2.16.0 might fix the vulnerability, but it also crosses two major API changes. Auto-Fix prefers the closest fix version: the minimum update that resolves the vulnerability. If 2.9.10.8 fixes the CVE, that is preferred over 2.16.0 because it minimizes the blast radius of the change.

For transitive dependencies, Auto-Fix traces the dependency chain to find the direct dependency update that pulls in the fixed transitive version. It checks each direct dependency's release notes and dependency declarations to find the minimum update path.

Phase 2: Compatibility Analysis

Before generating any code changes, Auto-Fix analyzes the compatibility impact of the proposed update.

For semantic versioning ecosystems (npm, Cargo, Go modules), it checks whether the update crosses a major version boundary. Major version changes are flagged for manual review because they likely include breaking API changes.

For ecosystems without strict semver (Maven, pip), Auto-Fix checks the changelogs and release notes of intermediate versions for keywords indicating breaking changes: "breaking," "deprecated and removed," "API change," "migration required."

It also checks whether the proposed update would conflict with other dependencies in the project. A version of Library A that requires Library B >= 3.0 creates a conflict if another dependency requires Library B < 3.0. Auto-Fix detects these conflicts and either finds an alternative resolution or flags the update for manual handling.

Phase 3: Pull Request Generation

For updates that pass compatibility analysis, Auto-Fix generates a pull request that includes:

  • Manifest file changes -- The updated version in package.json, pom.xml, requirements.txt, or whatever manifest format the project uses
  • Lockfile updates -- Regenerated lockfiles reflecting the dependency resolution with the new version
  • A detailed PR description -- The CVE being addressed, the old and new versions, the compatibility analysis results, and links to the advisory and release notes

The PR description is designed for quick review. It answers the three questions every reviewer asks: what vulnerability does this fix, what exactly changed, and is it likely to break anything?

Phase 4: Validation

If the repository has a CI pipeline, Auto-Fix lets the existing test suite validate the update. The PR is subject to the same CI checks as any other PR -- tests, linting, type checking, integration tests. If CI passes, the update is ready for human review and merge. If CI fails, Auto-Fix adds a comment to the PR explaining the failure and suggesting manual investigation.

Auto-Fix does not auto-merge. The final merge decision is always human. This is deliberate. Dependency updates can have subtle impacts that automated tests do not catch, and the responsibility for shipping changes should rest with the team that owns the code.

Configuration

Auto-Fix behavior is configurable at the organization and project level.

# .safeguard.yml
auto-fix:
  enabled: true
  strategy: minimum-update    # or latest-patch, latest-minor
  severity-threshold: high    # Only auto-fix high and critical
  exclude:
    - "lodash"               # Manual handling for specific packages
  max-prs: 5                 # Limit concurrent auto-fix PRs
  labels:
    - "security"
    - "auto-fix"

strategy controls how aggressively Auto-Fix updates:

  • minimum-update -- The closest version that fixes the specific CVE. Lowest risk, smallest change.
  • latest-patch -- The latest patch version within the current minor version. Slightly more aggressive, picks up all patch fixes.
  • latest-minor -- The latest minor version within the current major version. Most aggressive safe option, picks up features and fixes while staying within semver compatibility.

max-prs prevents Auto-Fix from overwhelming a repository with too many concurrent PRs. When the limit is reached, new fixes queue until existing PRs are merged or closed.

Grouped Updates

For projects with many vulnerable dependencies, Auto-Fix can group related updates into a single PR. If five dependencies all have vulnerabilities and all have straightforward updates, a single PR with five manifest changes is easier to review than five separate PRs.

Grouping is smart about risk. It will not group a low-risk patch update with a high-risk minor version bump. Updates are grouped by risk level so you can merge the easy ones quickly and give the complex ones dedicated attention.

Metrics

Auto-Fix tracks remediation metrics:

  • Mean time to fix -- From vulnerability disclosure to fix PR merged
  • Auto-fix success rate -- Percentage of vulnerabilities that Auto-Fix resolved without manual intervention
  • CI pass rate -- Percentage of Auto-Fix PRs that passed CI on first attempt
  • Manual override rate -- Percentage of Auto-Fix PRs that required manual modification before merge

These metrics help you understand how much of your remediation workload is being automated and where manual effort is still required. Over time, teams using Auto-Fix see mean time to fix drop from months to days.

Getting Started

Enable Auto-Fix in your project's Safeguard configuration and ensure the Safeguard GitHub App (or GitLab/Bitbucket integration) has permission to create branches and pull requests.

Start with severity-threshold: critical and strategy: minimum-update for the most conservative approach. As you build confidence in the automated updates, expand to high severity and consider more aggressive update strategies.

The first batch of PRs will cover your existing vulnerability backlog. From there, new vulnerabilities trigger fix PRs within hours of disclosure, keeping your backlog from growing.

Never miss an update

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