DedSec Application Security
A static analyser that flags every call to a dangerous function is doing pattern matching, and pattern matching produces a number rather than a priority. The number is usually large.
The problem is not that these findings are wrong. A raw SQL concatenation is genuinely worse code than a parameterised query. The problem is that "worse code" and "exploitable" are different predicates, and a queue that does not distinguish them trains its readers to ignore it. A team that treats every finding as equally urgent stops treating any of them as urgent.
Reachability is the attempt to answer the narrower question: can untrusted input actually get to this?
Taint analysis models three things. Sources, where untrusted data enters — a request parameter, a header, a message off a queue, a row in a table that something else populated. Sinks, where data reaching it causes harm — a query, a command, a template, a deserialiser, a file path. And sanitisers, the transformations that make tainted data safe for a particular class of sink.
The analysis propagates taint from sources through assignments, calls and returns, and reports the paths that arrive at a sink without passing through an appropriate sanitiser. The output is not "this line is dangerous" but "this input, through these five steps, reaches this sink" — which is both a better priority signal and a far better bug report, because it tells the engineer where the fix can go.
Interprocedural analysis is the part that matters. Real code almost never contains a source and its sink in the same function. The handler pulls a parameter and passes it to a service, which passes it to a repository, which builds the query. An analyser that only reasons within a single function sees a handler that reads input and does nothing dangerous, and a repository that builds a query from an argument of unknown origin. It flags the second one, or neither, and in both cases it is guessing.
AppSecD's taint analysis is interprocedural, tracing source to sink across function boundaries, and ships in two generations — v1 and v2 — which is worth knowing when you compare results between them.
Sanitiser modelling is where accuracy is won or lost. A sanitiser is only a sanitiser for a specific sink. HTML-escaping data does nothing for a shell command. Validating that a string is numeric neutralises most injection into a query and nothing at all about a path traversal. An engine with a coarse notion of "this was cleaned" suppresses real vulnerabilities; an engine with no notion of sanitisers at all reports every path.
The same question applies to dependencies, where the volume problem is far worse. A moderately sized application has hundreds of direct dependencies and thousands of transitive ones, and the advisory feed never stops.
Conventional composition analysis answers "do you have a version of this package that is affected". That is a manifest lookup, and it is the reason a monthly dependency report is mostly noise: the vast majority of vulnerable packages present in a build are vulnerable in a function your application never calls, on a code path that is never loaded, in a transitive dependency pulled in for a feature you do not use.
CVE reachability asks the next question: is the vulnerable code path reachable from your code at all. When the answer is no, the finding does not disappear — you still want it patched on the next routine dependency bump — but it does not need to interrupt anybody today. When the answer is yes, it moves to the front, and the path is right there in the finding.
Reachability is one input among several. AppSecD correlates advisories against the versions, manifests and repositories actually present in your estate, highlights CISA KEV entries, and shows blast radius per CVE — which repositories and services are affected. Reachable plus known-exploited plus present in a customer-facing service is a genuinely different item from reachable-but-obscure, and the ranking should reflect that.
This is the section most vendors leave out, and it is the one that keeps you safe.
Static reachability is an approximation, and it under-reports in specific, knowable ways:
The practical consequence: treat "not reachable" as a de-prioritisation, never as a dismissal. Findings that reachability demotes should still be visible, still ageing, and still fixed on the next routine pass — and anything with an unusual entry-point shape deserves a human look regardless of what the call graph says.
Reachability trims the queue. It does not empty it, and what remains still needs judgement.
AppSecD's AI layer labels likely false positives as part of a set of 27 configurable AI features that also cover fix suggestion and business-impact assessment. The property that makes this trustworthy rather than another opaque score is that the label is itself tracked: when a human disagrees with a triage decision, that disagreement is recorded against the label, so triage quality is measurable instead of asserted.
That is the standard to hold any automated triage to, ours included. Not "how accurate is it" as a marketing figure, but "can you show me, in my own data, how often it was wrong and in which direction". A suppression mechanism you cannot audit is indistinguishable from a suppression mechanism that is broken, and you will not find out which one you have until something that was suppressed turns up in an incident.