> TheAuditor / blog
• taint, engineering

A Proof Chain for Every Finding

TheAuditor rebuilt its interprocedural taint analysis. Every confirmed dangerous flow now carries a stored, queryable, hop-by-hop proof chain, so you can see exactly how untrusted input reached a dangerous operation instead of getting an unexplained alert.

An alert with no explanation is a guess you have to re-derive. Most scanners hand you “command injection at line 42” and leave you to reconstruct, by hand, how untrusted input actually got to that line. If you cannot follow the path, you cannot tell a real exploit from a false alarm, so the finding sits in a queue while someone reads three files to make up their own mind.

On 2026-08-29 we shipped an entirely rebuilt interprocedural taint engine. The headline is not that it reaches further, though it does. It is that every confirmed dangerous flow now carries its own explanation.

Every finding arrives with its receipts

When the engine confirms that untrusted input reaches a dangerous operation, it stores the full path that got it there: a hop-by-hop proof chain, from the point the value entered to the point it did damage, across functions and across files. That chain is kept with the finding, and you can query it. You are not handed a verdict and asked to trust it. You are handed the steps.

A proof chain reads like a route, one hop per line:

[0] entry_point   UploadController:31   POST /api/import   request body -> payload
[1] assignment    ImportService:12      payload.path -> targetPath
[2] call          ImportService:44      targetPath passed to readArchive(...)
[3] sink          ArchiveReader:20      targetPath reaches file open (Path Traversal)

Four hops, one unbroken line, with a file and a location at every step. The question “how does this input reach that sink” has an answer on the page instead of in your head.

When a flow changes languages, the chain says so

Real data does not respect file extensions, and a single value can begin its life in one language and end it in another. Every confirmed flow carries a cross-language flag, so when a path crosses a boundary the proof chain marks the crossing rather than quietly dropping it. The forensic work of following input from one language into the next has its own post. What changed here is that the crossing, like every other hop, is now recorded as evidence you can inspect.

A finding you can audit is a finding you can trust

This is the difference between an audit and an accusation. A stored proof chain means triage stops being archaeology: you read the path, you agree or you disagree, you move on. It means a finding survives the handoff, because the colleague you pass it to gets the same evidence you saw, not a line number and your word for it. And because the engine is built so that the same input yields the same facts, the chain you read today is the chain the next run produces, which is what makes it worth citing in a review at all.

Honest scope note

A proof chain tells you how a confirmed flow reached its sink. It is not a promise that the engine has modeled every construct in your codebase. Where analysis cannot follow a value, the tool reports the gap rather than inventing a path, and a chain is only ever built for a flow the engine actually confirmed. What we will not do is show you an alert and keep the reasoning to ourselves.

Where this sits

Auditable findings are the ground-truth layer for Code Reality Labs, held to an independent yardstick at BenchProctor. TheAuditor is in final commercial release preparation and ships when its hardening checks pass. Subscribe on the main site for launch news.

Was this useful?