What is exploitability validation?

Exploitability validation is the step that checks whether a reported vulnerability can be exploited, by running a safe version of the attack against the code, before anyone spends time fixing it. Static analysis tools report code that matches a risky pattern, and many of those reports are false alarms: the input was checked earlier, the code never runs, or the framework already escapes the output. Validation sorts the findings an attacker could use from the ones they couldn't.

Why static analysis produces false positives

Static application security testing (SAST) reads source code without running it. That lets it cover every line quickly, but it has to infer what happens at runtime. False positives usually come from one of these:

  • An unrecognized sanitizer. Input passes through a validation function the tool doesn't know about, so it still treats the input as dangerous.
  • Framework protection the tool doesn't model. Many template engines escape output and many database libraries parameterize queries automatically.
  • Missing context. A route behind an admin check, a function only ever called with constants, a feature switched off in production.
  • Code that never ships. Test fixtures, examples and dead code get scanned like production code.
  • Pattern matching. Rules that match the shape of risky code flag every instance of that shape.

When a tool can't decide, it usually reports, because a missed vulnerability is more costly than a false alarm.

What false alarms cost

Each alert takes someone's time to trace and dismiss, and a high false-positive rate also teaches a team to ignore the tool. A 2013 study by Johnson and colleagues, "Why Don't Software Developers Use Static Analysis Tools to Find Bugs?", found false positives and the way warnings are presented among the main reasons developers avoid these tools. Google's internal analysis platform, Tricorder, requires its checks to keep the effective false-positive rate below 10%, measured by how often developers mark a warning as not useful.

Measuring a scanner's accuracy

Two numbers describe a scanner:

  • Precision: the share of reported issues that are real.
  • Recall: the share of real issues that get reported.

The OWASP Benchmark measures both with thousands of small test cases, roughly half deliberately vulnerable and half deliberately safe, so a tool can't score well by flagging everything. It scores a tool as its true-positive rate minus its false-positive rate (the Youden index).

On the OWASP Benchmark for Java (2,740 test cases), Cyfendo raised 1,381 alerts, of which 1,331 were real: 96.38% precision, 94.06% recall and a 3.77% false-positive rate. On the Python benchmark (1,230 cases) the false-positive rate was 3.47%. The benchmarks page has the full counts and a comparison with other tools. These numbers measure detection only; the benchmark doesn't exercise the sandbox validation described below.

Reachability and exploitability

Reachability asks whether attacker-controlled input can get to the flagged code at all. It removes findings in dead code and in functions nothing calls. Reachable code can still be safe, though: the input may be validated on the way, or the dangerous call may only ever receive values from a fixed list.

Exploitability asks whether a specific input produces a specific harmful result, such as returning another customer's records or running a command on the server. Running the attack is the only way to answer it with certainty.

Ways to validate a finding

  1. Manual triage. A security engineer reads the code and decides. Accurate, slow, and unavailable to most small teams.
  2. Reachability analysis. Automated and fast, but it can't separate reachable-and-safe from reachable-and-exploitable.
  3. Testing the running app. Dynamic scanners and penetration tests attack a deployed app from outside. Convincing when they succeed, but they need a deployed environment and only see what is exposed externally.
  4. A proof of concept in a sandbox. Run the specific attack against a disposable copy of the code and observe the result. This is automatic, and it happens before deployment.

How Cyfendo validates findings

  1. Trace. Cyfendo follows untrusted input through the code across files and flags paths where it reaches a database query, file path, shell command or another user's data without being made safe.
  2. Attack in a sandbox. For each flagged path it writes a proof-of-concept attack and runs it against a disposable copy of the app. External services are replaced with stand-ins; Supabase apps get a stand-in Supabase with two test users built from the project's migrations.
  3. Compare with a harmless request. The attack must produce the harmful result, and a harmless request on the same path must behave normally. This keeps a crash or error page from counting as proof.
  4. Report. Reproduced issues are reported with fix steps. Findings that couldn't be reproduced remain listed in the dashboard.
  5. Test the fix. Patches are checked by replaying the original attack against the patched code and running the project's tests, and each patch states how it was tested.

Limits

  • A finding that wasn't reproduced may still be real. Some attacks depend on production configuration, the real behavior of a third-party service, or timing that a sandbox doesn't reproduce, so unreproduced findings stay listed in the dashboard.
  • The code has to run. Validation depends on the language toolchain being available and on stand-ins for the services the app uses.
  • It tests code, not intent. It can show that user B can read user A's records. Whether managers should see their own team's records is a rule only the app's owner can define.

Cyfendo validates findings the same way whether it scans a repository, runs from the CLI, or is called by an AI coding tool such as Cursor, Claude Code or Lovable.

See what Cyfendo finds in your code.

Free for apps up to 10,000 lines of code. No credit card.