Aikido

What is vulnerability remediation?

Written by
Nicholas Thomson

Vulnerability remediation is the process of fixing security flaws, whether they live in code your team wrote, the open-source packages you depend on, the containers you ship, or the cloud accounts you run in. Vulnerabilities have become the most common way attackers get in. The 2026 Verizon Data Breach Investigations Report found that vulnerability exploitation overtook stolen credentials as the top initial access vector for the first time, accounting for 31% of breaches, up from 20% the year before.

Most teams already know about more vulnerabilities in their code than they can fix. The same report found that only 26% of the vulnerabilities on CISA's Known Exploited Vuln (KEV) catalog were fully remediated in 2025, and the median time to patch one stretched to 43 days. 

This guide covers the vulnerability remediation process step by step, how to prioritize what to fix first, and how to fix each type of vulnerability, along with what to do when upgrading a dependency isn't an option. If you're looking for tools that handle this work, see our roundup of vulnerability remediation tools.

{{cta}}

Where the vulnerabilities are

Your own code

Vulnerabilities in code your team wrote fall into two groups requiring two different segments of the security stack. Pattern-based flaws are the ones deterministic SAST catches on every commit.

Pattern-based flaws
Caught by deterministic SAST on every commit
Logic flaws
Need AI reasoning about the code, or a pentest against the running app
  • SQL injection
  • Cross-site scripting (XSS)
  • Command injection
  • Path traversal
  • Server-side request forgery (SSRF)
  • Insecure deserialization
  • XML external entity (XXE) injection
  • Weak or misused cryptography
  • Broken access control
  • Insecure direct object references (IDORs)
  • Privilege escalation across service boundaries
  • Authentication bypass
  • Business logic flaws, like a subscription tier check missing on one endpoint
  • Exploit chains, where several low-severity issues combine into an account takeover

SAST is a rules-based, deterministic engine that works by pattern matching. It works well for flaws with a recognizable shape like "if user input flows into this function without going through a sanitizer, flag it as SQL injection." Logic flaws have no such shape. There's no pattern for an endpoint that should check whether the user owns a resource and doesn't, so catching these means reasoning about what the code is supposed to do. That's the job of AI code review, which reads the code with that intent in mind, and AI pentesting, which probes the running app to prove whether a flaw can actually be exploited.

Both types of vulnerability remediation require code changes by whoever owns the code. Pattern-based fixes follow well-known recipes like parameterizing a query or encoding output. Logic flaws depend on what the code was supposed to do, so fixing one takes the same understanding of the application that it took to find it. When an AI tool has already traced how a missing authorization check can be exploited, it can propose a fix built on that analysis, and the reviewer gets an explanation alongside the change.

Open-source dependencies

Most of the code in a modern application comes from open-source packages, and most of those are transitive dependencies pulled in by the packages you  chose. So most of the vulnerabilities here live in code nobody on your team wrote, or even picked.

Software composition analysis (SCA) reads your lockfiles to build the full dependency tree, then checks each package version against a source of vulnerability data. That source decides what it catches. Tools that rely only on public CVE databases miss the open-source flaws that get fixed in a release without a CVE ever being assigned, which is why some SCA tools, Aikido's included, draw on threat intelligence feeds like Aikido Intel.

A finding doesn't tell you whether the vulnerability matters to you. A CVE in a function your code never calls isn't reachable and poses little real risk, while the same CVE in a function you use everywhere is worth dropping other work for. A CVSS score won't tell them apart, since it rates the flaw in the abstract, not how exposed your app is. 

SCA checks have to keep running after you merge. The package versions in your lockfile stay pinned while new vulnerabilities keep being disclosed against them, so a dependency tree that passed last month can fail today without anyone touching it. When a finding does come in, the standard fix is to upgrade to a release that patches it, and the next section covers why that upgrade so often turns into a bigger job than it looks.

Container images

Most of what's vulnerable in a container image comes from the base it's built on. A typical base image ships with dozens of system libraries and tools, like a shell and a package manager, and container image scanning is what checks those OS-level packages. Images also drift in a way that's easy to miss. A running container keeps the packages it was built with until someone rebuilds and redeploys it, so a container running in production can not get a fix that exists upstream for months.

Fixing an image comes down to how much of that foundation you're willing to change. Removing packages your runtime never uses shrinks the problem. For everything that stays, upgrading to a newer base tag or migrating to another vendor's hardened distro both mean testing your app against a different foundation, while a patched build of the same base version closes the CVEs and keeps everything else as it is.

Infrastructure as code (IaC)

IaC moves cloud configuration into files like Terraform and CloudFormation templates, Helm charts, and Kubernetes manifests, so most of your cloud setup can be reviewed like any other code. Typical vulnerabilities include:

  • A storage bucket open to the internet
  • A security group that accepts traffic from anywhere
  • A container running as root
  • An EC2 instance still using IMDSv1, the older version of AWS's metadata service that SSRF attacks rely on to steal credentials

IaC is the easiest place to fix a cloud misconfiguration, because nothing has been applied yet. IaC checks run in your CI/CD pipeline and flag these in the pull request, and the fix is a corrected template, often a one-line change, that never reaches a live environment. The catch is that IaC checks only see what's written in your templates.

Cloud configuration

In a mature engineering org, most cloud infrastructure is defined in IaC, so many cloud findings are really IaC findings that made it through. The rest come from changes nobody wrote down. Someone clicks through the console to open a port or widen a role, and no template or pull request records it.

Cloud security posture management (CSPM) reads the live account directly, so it catches those changes along with anything that slipped past review. The fix is a config change or a tightened policy, and it needs to make its way back into IaC. If the resource is already managed by a template, a console-only fix gets reverted by the next deploy. If it was created by hand, bringing it under IaC means the next change to it goes through review.

Some of the most serious findings span layers, and the MLflow SSRF flaw (CVE-2026-64849) shows how. Within hours of it being assigned a CVE in August 2026, attackers were exploiting it to make MLflow servers ask the cloud provider's metadata service for their own credentials. On AWS, IMDSv1 hands those over in response to a simple request. IMDSv2 requires a session token first, an extra step most SSRF bugs can't perform, so enforcing it would likely have blocked the theft. 

Whatever credentials attackers did get were only as powerful as the IAM role attached to the server, and since those roles usually live in Terraform or CloudFormation too, IaC checks can catch an over-broad policy before it's deployed. Both safeguards sit in the same templates IaC checks already read, which makes IaC the cheapest place to stop an attack like this.

Secrets

Secrets often end up in code by accident. An API key gets hardcoded in a test, or a database password slips into a config file that gets committed with everything else. AI written code tends to have this problem in particular. Secrets detection checks new commits and the full git history for these, and a pre-commit hook can block one before it's ever committed. Container images need the same check, since a secret copied into one layer stays in the image even if a later layer deletes it.

Deleting the secret from the code doesn't fix it, because it's still in git history. The fix is to rotate the credential, then checking access logs to see whether anyone used the old one before you rotated. If the logs show someone else used it, you have to figure out what the attacker accessed and whether the data involved triggers any breach notification requirements. Once the old credential is dead, scrubbing it from history is good housekeeping but no longer urgent. To keep it from happening again, move the secret into a secrets manager or an environment variable the code reads at runtime.

When upgrading a dependency isn't an option

Most SCA tools and security advisory gives the same advice for a vulnerable package, which is to upgrade to the version with the fix. For a patch-level bump, that's usually all it takes. The trouble starts when the fix doesn't arrive that neatly, and in practice it often doesn't.

The trouble starts when the fix only exists in a new major version with breaking API changes, or when the vulnerable package is transitive and your upgrade is waiting on a maintainer three levels up the tree. Abandoned packages and end-of-life versions never get a patched release at all, and upgrading on reflex is how the hijacked versions of chalk and debug reached pipelines within minutes. So teams defer the upgrade, and the CVE goes on an ignore list that only grows.

CVE-2026-48937 in Node.js shows how this plays out. The fix shipped alongside a semver-major update to nghttp2 that removed HTTP/2 priority signaling entirely, because the vulnerable behavior and the removed feature came from the same underlying code. For a team running an HTTP/2 service, a one-line version bump turned into a hunt for every call to setPriority and .priority(), in their own code and in any dependency relying on the same APIs, while the CVE stayed open.

Backporting is the most direct way out, applying the fix to the version you already run. You can fork the package and do it yourself, though you then own that fork, or use a patched build from a vendor that maintains backports, which Aikido Security offers for open-source packages and container images. You can close the CVE and upgrade when your team has time to test it properly.

Vulnerability remediation best practices

Set SLAs by risk

Once you've ranked findings by exploitability and exposure, give each risk tier a deadline your team can meet. A service-level agreement (SLA) measured in days for a KEV-listed vulnerability on an internet-facing service, and in weeks for a reachable medium in an internal tool orders the queue. Track misses against those SLAs as well, since a pattern of misses in one team or one layer usually points to a process problem worth fixing.

Put fixes where developers already work

A finding that lives in a security dashboard competes with everything else on a developer's plate, and it usually loses. Surfacing it in the IDE while the code is being written, or in the pull request before it merges, means the developer sees it while the change is still fresh in their head. That's when they have the most context about what the code is meant to do, and when fixing it costs the least, before it's shipped. It also settles the ownership question, because whoever opened the pull request is the obvious person to fix it.

Automate fixes that don't change behavior

Backported patches and patch-level bumps that pass your tests can merge with a light review, because they close a CVE without changing how your code behaves. Fixes for logic flaws like an IDOR or a missing authorization check do change behavior, so they're most useful when they arrive with the reasoning behind them, showing how the flaw could be exploited and what the fix enforces, which makes the review fast. Upgrades that cross a major version are where automation helps least, and the upgrade trap section above covers better options for those. 

Re-test before closing

Re-run whatever found the vulnerability against the fixed version, and close the finding only once it no longer appears. For findings in a running app, that means re-testing the deployed environment, since a fix that passes in a branch can still fail behind a misconfigured proxy or an old build that never got redeployed.

‍

How Aikido Security handles vulnerability remediation

Aikido Security covers remediation from the first sign of a vulnerability through to the pull request that fixes it. It starts with Aikido Intel, which tracks vulnerabilities in open-source packages before they're assigned a CVE, including plenty that never will be, so remediation can begin ahead of the public databases. 

Aikido Security remediation flow

Every finding then goes through two stages of triage. Reachability analysis traces whether your code has any execution path to the vulnerable function, which clears out CVEs in packages you pull in but never exercise. What's left goes to CVE Exploitability Analysis, an agent that reasons about how your code actually uses the package and then acts on each finding, raising the severity when a CVE is more dangerous in your setup than its base score suggests, lowering it when it's less, snoozing findings to revisit later, or ignoring the ones that aren't exploitable at all. Together they cut noise by up to 95%.

Fixes arrive as AutoFix pull requests. For code and IaC findings, AutoFix writes the change itself. For dependencies and containers, the fix is a backport. Aikido Libraries produces patched builds of the package versions you already run across npm, PyPI, Maven, and Go, so the CVE closes without a version bump or an API change, even when no patched release exists upstream. Aikido Images does the same at the container layer, with 2,000+ drop-in replacement images that clear high and critical CVEs to a defined SLA on the OS version and distro you already use. 

Both ship as daily AutoFix pull requests in the workflow your team already uses. A pull request still has to be tested and deployed before the vulnerability is actually gone, and that's the step AutoShip handles. Add a label to an AutoFix pull request and AutoShip carries it from CI through staging to production, running smoke tests and watching for regressions along the way, so the fix reaches production without pulling a developer off what they're building.

Aikido also contributes backported fixes for KEV-listed vulnerabilities to the open-source community for free, so the flaws attackers are actively using get patched for everyone, customer or not. And because every fix runs through the same platform, each one is recorded as compliance evidence for SOC 2 and the ISO standards Aikido supports, including ISO 27001 and ISO 42001.

{{walkthrough}}

Share:

https://www.aikido.dev/blog/vulnerability-remediation

Subscribe for news

4.7/5
Tired of false positives?

Try Aikido like 100k others.
Start Now
Get a personalized walkthrough

Trusted by 100k+ teams

Book Now
Scan your app for IDORs and real attack paths

Trusted by 100k+ teams

Start Scanning
See how AI pentests your app

Trusted by 100k+ teams

Start Testing
Close vulnerabilities without the headache

Avoid the upgrade trap with backported patches for the versions you already run

Start Now

Get secure today,
quickly and for free.

Secure your code, cloud, and runtime in one central system.
Connect a repo to discover what the reasoning agents find in your codebase.

No credit card required | Scan results in 32 seconds.
Trusted by 150k+ orgs