Safeguard
Security Guides•

Write the failing test first when you fix a vulnerability

A fix for a vulnerability should arrive with a test that fails before the change and passes after. Here is the pull request checklist to enforce it.

Safeguard Security Team
3 min read

When you fix a vulnerability, first write a test that reproduces it and fails. Then make the fix and watch the test pass. The test proves the fix works, and it stays in the suite so the same bug cannot quietly return in a later refactor.

Why this order

Fixing first and testing after tends to produce a test that passes for the wrong reason. If you have never seen the test fail, you do not know it can.

A failing test also forces a precise statement of the bug. "Users can read other users' files" becomes a concrete request with a concrete wrong response.

The steps

  1. Reproduce the issue by hand and write down the exact request or input.
  2. Encode it as an automated test at the lowest level that still shows the failure.
  3. Run it and confirm it fails, for the right reason.
  4. Make the smallest change that fixes the cause.
  5. Run it again and confirm it passes, along with the rest of the suite.
  6. Add variations: neighbors of the same bug, such as the same missing check on a sibling route.

Where the test should live

Choose the lowest level that reproduces it. A missing escape in a template is a unit test. A missing owner check on a route is an integration test. A parser crash is a fuzz corpus entry. Go's fuzzing documentation says a failing fuzz input is written to the testdata directory and replayed by a plain test run, which makes it a regression test automatically.

Dependency vulnerabilities

For a vulnerable library, the equivalent is a test that exercises the vulnerable code path in your application, if one exists. Upgrading the package alone leaves no proof. If you cannot reach the vulnerable function, say so in the pull request and note why. Version bumps should still pass the existing suite plus any test that covers behavior the upgrade could change.

Pull request checklist

  • Link to the report or advisory.
  • A test that fails on the base commit. Some teams run the new test against the parent commit in CI to prove it.
  • The fix and the test in the same pull request.
  • A note on related places checked for the same flaw.
  • No details in the public commit message that would help exploitation before users can upgrade, where disclosure is still coordinated.

Try it yourself

The fix available demo shows how a fix is surfaced for a finding. Look at what evidence it gives you, then ask what test would prove the fix in your own code.

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

Quick check

What if the bug is hard to reproduce in a test?

Narrow it. Extract the logic into a function you can call directly, or add a seam for time or randomness. If it truly cannot be automated, document a manual verification step and keep the ticket open until it is done.

Safeguard can open fix pull requests through autonomous remediation, which is off by default and starts with every category on Manual, so a person reviews each change and its tests.

Sources

Last reviewed: 19 October 2026.

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.