I pointed a full scanning stack at a deliberately vulnerable test project last week — the kind of repo that has a hardcoded AWS key in it, a public S3 bucket in the Terraform, an ancient Django version, and an eval() on user input, all on purpose. Eight scanners, every category covered.

It came back with 223 findings. And that number is the entire problem with how most security scanning gets delivered.

223raw findings
26were duplicates
197actual issues
105high or critical

223 lines of output is not a deliverable. It's a spreadsheet you email to someone who then has to become a security engineer for a week to figure out which twelve things actually matter. The scan is the easy part — it's about four minutes of compute. Everything that makes the result usable happens after.

Here are the three things that have to happen between the scan finishing and a report being worth paying for.

1. The same issue reported three times is not three issues

Serious scanning means running more than one engine per category. No single open-source scanner has complete policy coverage or a complete vulnerability database — so you run two for infrastructure-as-code, two for dependency CVEs, and reconcile the results. Coverage goes up. So does noise.

In that 223-finding run, 26 findings were the same underlying problem found by more than one engine. One line in one Terraform file — a bucket with a public ACL — got reported separately by three different scanners, each with its own wording, its own rule ID, and its own severity rating. Ship that raw and your client fixes one bucket and still has two open tickets about it.

Why this is harder than it looks Two scanners describing the same misconfiguration rarely agree on anything you can match on automatically. Different rule IDs, different titles, sometimes different line numbers for the same resource. Deduplication has to happen on what the finding means, not on what it says.

2. Severity is not the same thing as urgency — and sometimes it isn't even severity

Most scanners export their results in SARIF, the industry-standard interchange format. It's a genuinely useful spec, but it has a quirk that bites anyone who trusts it naively: SARIF's severity field is an enum with four values — none, note, warning, and error. There is no "critical".

So when a scanner finds a CVE with a CVSS score of 9.8, it has to write error in the severity field, exactly like it would for a 7.1. The real score is still in the output — but it's tucked into a per-rule properties bag, in a different place for every tool. Read the obvious field and every critical in the report quietly becomes a high.

That's not a hypothetical. It's a bug I found in my own pipeline by cross-checking normalized output against what each scanner actually reported, and it had been silently capping severity on every critical finding. Anyone building on top of scanner output should go and check this right now.

Executive summary page of a security assessment report showing a severity distribution bar and a findings-by-area table
Executive summary from a real report — severity distribution and findings grouped by area, so the first page answers “how bad is this?” before anyone opens a ticket.

3. A finding without a fix is just homework

This is the one that actually decides whether a security report is worth anything.

Most scanner output tells you what's wrong and stops. "S3 bucket has a public ACL." "Service account has excessive privileges." Technically correct, completely unactionable — the person reading it now has to go and research the fix, which is the expensive part, and which is exactly what they were paying someone else to already know.

A finding is only finished when it carries the fix with it. Three forms, depending on what's broken:

  • Infrastructure as code — the actual snippet, ready to paste into the module.
  • Live cloud configuration — the exact command, with the real resource names filled in.
  • Everything else — the specific steps, in the right order. (Rotate the leaked credential before you rewrite git history. Do it the other way round and the key is still valid while you're busy cleaning up.)
A report finding showing a Terraform code snippet as the remediation, with the file and line number of the issue
An infrastructure-as-code finding: the exact file and line, and the Terraform to fix it — not “review your encryption configuration”.

For cloud-account findings, the same rule applies, plus one more thing worth carrying: which compliance controls the finding actually maps to. If a startup is working toward SOC 2 or ISO 27001, "this is CC6.1" is the difference between a security ticket and an audit-evidence ticket.

A report finding showing exact CLI commands to remove an over-permissioned role binding, plus the CIS and SOC 2 controls the finding maps to
A cloud-posture finding: the exact commands to run, and the CIS / SOC 2 controls it affects.

And the same remediation has to survive the export. A CSV that drops the fix column is just the wall of noise again, in a different file format — so every row carries its own remediation inline, ready to be split across a team without anyone having to go back to the PDF.

CSV export of security findings where each row includes a remediation column containing the exact CLI command or Terraform snippet
The CSV export — every row carries its own fix, so findings can be assigned without losing the remediation.

What this means if you're buying a security audit

Anyone can run the scanners. They're open source, they're free, and most of them are one brew install away. If a security report you're paying for looks like it could have been produced by piping a tool's default output into a PDF, it probably was.

The questions worth asking before you buy one:

  • Does every finding come with a specific fix, or just a description of the problem?
  • Has the output been deduplicated across engines, or am I getting the same issue three times?
  • Are the severities the scanner's raw output, or has someone checked them against the real scores?
  • Does it tell me the exact file and line — or the exact resource — so I can act without hunting?
  • If I'm working toward a framework, does it tell me which controls each finding touches?

Findings are cheap. Fixes are the product.

This is the report format from a fixed-fee cloud security audit — read-only access, findings ranked by what's actually exposed, and an exact fix on every line.

See the cloud security audit →

📢 Have questions or feedback? Drop a comment below or connect with me on Twitter/X@spysood!