The cost of ignoring it
The widely-cited global average cost of a data breach is $4.88 million (IBM’s annual Cost of a Data Breach study). For an enterprise, that is a bad quarter. For a fifteen-person company, one exploited vulnerability can be the end. The arithmetic is not complicated: the expected cost of an incident is the probability times the damage, and you cannot reduce the damage of a breach you never discovered.
The uncomfortable part is not the price. It is the timing. Most teams find out what they had from an attacker, not from a tool, and the interval between exposure and discovery is where the real loss happens.
What scanning is genuinely good at
Let us be clear about this first, because the rest of the article is often misread as an attack on scanners. Scanning is good at three things, and it is good at all three:
- It is fast. A repository-wide pass in seconds means it can run on every commit, and a control you can run continuously beats one you run quarterly.
- It is wide. One pass covers every file, every dependency and every secret, including the parts of the codebase nobody remembers writing.
- It is cheap and repeatable. This is the part that matters. The value of a control is not its accuracy, it is how often you run it.
If you run nothing, you have no chance of finding the vulnerability that gets exploited. So run something. We publish ours as a free, open-source API, and the honest recommendation is to point it at every repository you own, today, at no cost.
A scanner tells you where a bug might be. Everything that follows — deciding whether it is real, fixing it, and stopping it coming back — is still a human problem. The interesting question is how much of that a machine can do for you now.
The three things a scan cannot do
Here is the gap, stated precisely. A scan, however good, produces a list. Three things have to happen after that list exists, and a scan does none of them.
1. Prove the attack path actually works
A pattern match finds code that looks wrong. A reachable vulnerability in production is a different thing: it depends on the configuration, the deployment, the data, and the path to it. The difference between the two is exactly the difference between a report that gets triaged for a week and a breach.
Proving it means executing the path against the running system and keeping the request and the response. A scanner cannot do that. A team that attacks can.
2. Apply the fix and prove it did not break anything
A finding you have to fix yourself is a finding you will postpone. And a patch is not a fix until it passes the test suite of the codebase it lives in — a change that silences the scanner and breaks a legitimate flow is a regression with a clean scan result.
3. Leave a detection that catches the next attempt
This is the one almost nobody closes. If an attacker reached the vulnerable path once, they will try it again, and the only reason their second attempt is expensive is that your logging noticed. A finding without a detection is a finding that has not been closed, only documented.
What changed in 2026, and what did not
Models genuinely improved the reading part. A model understands code context rather than matching patterns, so it catches the odd business-logic flaw that a rule never will, and it ranks findings by how they are actually reachable instead of by which rule fired. That is a real gain and it is why AI-assisted scanning is worth having.
What did not change is the ability to execute. A model reading your code has never sent a request to your API, never seen what your authorisation middleware actually does, and never watched a payload come back. The three gaps above are not implementation details. They are the difference between reading about an attack and performing one.
What we do instead
We run the loop. Attack the target, reproduce the finding end to end, land the fix as a diff that passes your suite, write the detection and prove it fires, then re-test the fix on a clock so a regression is caught by us before an attacker catches it again.
One redacted example, so you can see the shape of it. A cross-tenant read in a multi-tenant API:
01 ATTACK GET /api/v1/orders/9812
Authorization: Bearer <tenant-A token>
-> 200 OK, tenant B's order
02 VERIFY 10/10 foreign ids return 200 with another tenant's data
no owner_id comparison on the route
03 PATCH - order = Order.objects.get(id=id)
+ order = get_object_or_404(Order, id=id,
+ tenant_id=request.tenant.id)
04 DETECT when route == "/api/v1/orders/*"
and status == 200
and order.tenant_id != session.tenant_id:
alert("precog.idor.cross_tenant_read")
block(response)
05 PROVE def test_cannot_read_other_tenant_order(client):
r = client.get("/api/v1/orders/9812", headers=A)
assert r.status_code == 404
# before patch: 200 -> test fails
# after patch: 404 -> test passes
Four artefacts per finding: the attack, the reproduction, the patch and the test — plus the detection. The worked example on our site shows the full format with the raw evidence.
Five questions to ask any security vendor
Including us. If a vendor cannot answer these plainly, the answers you are getting are marketing.
- What happens to a finding you cannot reproduce? If the answer is "it still goes on the list", the list is a list of suspects, not of vulnerabilities.
- Does the fix come back as a diff that passes our test suite? If the answer is "we will describe the fix", you are doing the work.
- Which detection ships with it, and how do you know it fires? If the answer is "your SIEM will pick it up", it will not.
- What happens to the fixes you shipped, six months later? If the answer is "re-scan and hope", the fixes are unowned.
- Who did the work, and can I see it? "An automated platform" is not an answer unless you can also see its evidence.
What to do on Monday
- Scan every repository you own. Free, fast, and the baseline you are currently missing. Use the open-source scanner API, or run it in CI.
- Wire it into the pipeline. A scan on every commit beats a scan at release. If it is slow, it will be skipped.
- Re-scan after every dependency change. Most new exposure arrives through a version bump, not through new code.
- Pick three findings. Do you have the reproduction, the patch and the detection? If any of the three is missing, that finding is not closed.
- Check your logs for the last attempt. If you cannot tell whether anyone tried the same path before, you have no detection either.
The short version
Run a scanner. It is cheap, it is fast, and it is the only way you find out what you have. Then understand what it does not do, because the gap between “found” and “fixed” is where every breach actually lives. And if you want that gap closed rather than just logged, that is a different kind of service, and it is what we do.
Get a Free Automated Scan See what an engagement includes
Prefer the scanner API on your own infrastructure? It is open source and free: tim777z/precog-api. Found something in your codebase that you want a second opinion on, or a vulnerability in ours? Tell us — our coordinated disclosure policy is published here.