<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[BreachLine Labs]]></title><description><![CDATA[BreachLine Labs]]></description><link>https://breachlinelabs.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6ad4f42a48fd4542555e01ea/bc324950-2724-4c81-bd95-48381ecd9297.png</url><title>BreachLine Labs</title><link>https://breachlinelabs.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 23 Oct 2026 03:59:30 GMT</lastBuildDate><atom:link href="https://breachlinelabs.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[You Fixed the Vulnerability. Now Prove It: A Simple Retest Checklist]]></title><description><![CDATA[A short, practical checklist for confirming that a security fix really worked.]]></description><link>https://breachlinelabs.hashnode.dev/you-fixed-the-vulnerability-now-prove-it-a-simple-retest-checklist</link><guid isPermaLink="true">https://breachlinelabs.hashnode.dev/you-fixed-the-vulnerability-now-prove-it-a-simple-retest-checklist</guid><category><![CDATA[Security]]></category><category><![CDATA[DevSecOps]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[BreachLine Labs]]></dc:creator><pubDate>Sun, 18 Oct 2026 16:37:07 GMT</pubDate><content:encoded><![CDATA[<p>A security ticket gets closed. The code was changed. The pull request was approved. Everyone moves on.</p>
<p>But was the issue actually fixed? Often nobody checks. At BreachLine Labs we think that last step deserves its own checklist. Here is the one we would hand to any team.</p>
<h2>1. Why "fixed" is not the same as "safe"</h2>
<p>Fixes fail in quiet ways. Some common ones:</p>
<ul>
<li><strong>The twin endpoint.</strong> You patch <code>/api/v2/orders/{id}</code>, but <code>/api/v1/orders/{id}</code> still works and has the same bug.</li>
<li><strong>The symptom, not the cause.</strong> You block one bad input, but a slightly different one gets through.</li>
<li><strong>The fix that gets undone.</strong> A later refactor, a merge, or a config change quietly brings the issue back.</li>
</ul>
<p>None of these are rare. That is why a fix needs a retest, not just a review.</p>
<h2>2. Start from the original proof</h2>
<p>Before anything else, find the evidence that showed the issue in the first place. That might be:</p>
<ul>
<li>the exact HTTP request and response</li>
<li>the steps a tester followed</li>
<li>the test accounts and roles they used</li>
</ul>
<p>Re-run those steps first, exactly as before. If the original proof no longer works, that is a good start. If it still works, the fix is not done.</p>
<p><strong>Tip:</strong> if your tickets do not keep this evidence, start now. A finding without reproduction steps is very hard to retest.</p>
<h2>3. Test around the fix, not just on it</h2>
<p>Attackers rarely try only the exact thing you patched. Neither should you.</p>
<p>Imagine you fixed an access control bug where user A could read user B's invoice. Now check:</p>
<ul>
<li><strong>Similar endpoints.</strong> Can user A still read B's receipts, orders or profile?</li>
<li><strong>Other roles.</strong> Does the fix hold for admins, guests and API keys?</li>
<li><strong>Other encodings.</strong> Does the check still apply if the ID is sent in a different format, or in the body instead of the URL?</li>
<li><strong>Older versions.</strong> Is an older API version still live, and does it have the fix?</li>
</ul>
<p>A short list like this catches most "fixed here, broken there" problems.</p>
<h2>4. Quick re-checks for config fixes</h2>
<p>Some fixes are not code. They are settings. Security headers, cookie flags, TLS settings and CORS rules are common examples.</p>
<p>These are easy to get right in a pull request and wrong in production. A proxy, a CDN or a different environment can change what users actually receive.</p>
<p>So check them live, after deploy:</p>
<ul>
<li>Are the security headers you added actually being sent?</li>
<li>Do session cookies have <code>Secure</code>, <code>HttpOnly</code> and a sensible <code>SameSite</code> value?</li>
<li>Is the CORS policy as tight in production as it was in review?</li>
</ul>
<p>For header fixes, a quick live check helps. A free <a href="https://breachline.io/tools/security-headers">security headers check</a> shows what your site actually sends after deploy.</p>
<h2>When the fix is a dependency upgrade</h2>
<p>Some fixes are just a version bump. A library had a known flaw, and you upgraded it. That sounds simple, but it is worth a quick check.</p>
<ul>
<li><strong>Did the new version actually ship?</strong> Look at the lockfile and the built artefact, not just <code>package.json</code> or <code>requirements.txt</code>.</li>
<li><strong>Is the old version still pulled in somewhere?</strong> Another package may depend on it. Check the full dependency tree.</li>
<li><strong>Did anything else change?</strong> A big upgrade can bring new install scripts or new sub-dependencies. Review the lockfile diff before you merge.</li>
</ul>
<p>If you can, re-run the original proof against the upgraded build too. A version number is a claim. A failed exploit is evidence.</p>
<h2>5. Stop it coming back</h2>
<p>The best retest is one that runs by itself.</p>
<p>Where you can, turn the original proof into an automated test in CI. For example:</p>
<pre><code class="language-python">def test_user_cannot_read_other_users_invoice(client, user_a, user_b_invoice):
    client.login(user_a)
    response = client.get(f"/api/v2/invoices/{user_b_invoice.id}")
    assert response.status_code in (403, 404)
</code></pre>
<p>Now if a later change brings the bug back, the build fails. You find out in minutes, not months.</p>
<p>Not every issue can be tested this way. Config and infrastructure issues may need a scheduled check instead. But anything you can automate, you should.</p>
<h2>6. Record the result</h2>
<p>Before closing the ticket, attach the evidence. A good record includes:</p>
<ul>
<li>the original proof</li>
<li>the retest steps you ran</li>
<li>the result, with a request and response or a screenshot</li>
<li>the date and who ran it</li>
</ul>
<p>It also helps to use two different words. <strong>Fixed</strong> means the code changed. <strong>Verified fixed</strong> means someone re-ran the proof and it failed. Only the second one should close a security ticket.</p>
<h2>7. When to bring in a fresh pair of eyes</h2>
<p>The person who wrote a fix is not always the best person to test it. They know what they meant to do, so they test that.</p>
<p>For high-risk issues, ask someone else to retest. That might be another developer, your security lead, an external tester, or an automated tool you trust. Fresh eyes try things the author did not think of.</p>
<h2>The checklist, in one place</h2>
<ol>
<li>Keep the original proof.</li>
<li>Re-run it exactly.</li>
<li>Test similar endpoints, roles, encodings and versions.</li>
<li>Re-check config fixes live, after deploy.</li>
<li>Turn the proof into an automated test where you can.</li>
<li>Record the evidence, and use "verified fixed".</li>
<li>Get a second person or tool to retest high-risk fixes.</li>
</ol>
<p>It takes a little longer than closing the ticket. It saves a lot more time than finding the same bug twice.</p>
<hr />
<p><em>About the authors: the BreachLine Labs team builds Nebula, an autonomous AI security engineer that proves impact with working exploits and retests fixes.</em></p>
<p><em>Drafted with AI assistance and reviewed and tested by the BreachLine Labs team.</em></p>
]]></content:encoded></item></channel></rss>