security · governance

Why data due diligence needs corroboration, not detection

Elijah Ally, Founder · Published 2026-08-04 · 7 min read

A check performed at one moment, over only the data someone chose to show you, cannot tell the difference between clean and hidden — and the fix is not a smarter detector.

In June, Plaid published a whitepaper written by Javelin Strategy & Research called “From Data to Decision: Detecting Fraud Risk Earlier.” It is a fraud report, sponsored by a fintech company, written for banks and credit unions. On its face it has nothing to do with database tooling.

We read it anyway, because it makes an argument we have spent the last year arriving at from a different direction. Javelin’s version is about fraudsters moving between banks. Ours is about facts moving between systems. Same structure, same failure, same fix — and the fix is not a better detector.

What fraud teams learned the expensive way

The numbers first, because they set the stakes. Javelin surveyed 5,010 U.S. adults between November and December 2025. Identity fraud cost consumers over $27 billion that year; scams cost nearly $11 billion more. New-account fraud was the only category where both the number of victims and the dollars lost went up — 31% more victims, 13% more losses.

The structural finding matters more than the totals. Most fraud programs are organized around decision points: onboarding, login, a profile change, a payment, a dispute. Fraudsters are not. They move across accounts, products, and organizations, testing controls and reusing data as they go — so by the time one organization sees fraud, the related activity often already exists somewhere that never told anyone.

Javelin is blunt about the cause, and it is not the one people expect. The problem is usually not missing data. The data exists — split across teams that do not talk to each other, where onboarding sees identity, authentication sees devices, payments sees the transaction, support takes the claim, and none of it feeds back.

The risk was visible the whole time. It just was not visible to anyone in a position to act on it.

Absence is not absolution

Now move that shape into a database. It appears whenever you are asked to verify data you did not produce: a fundraising data room, a vendor security questionnaire, technical diligence before an acquisition. Someone connects a database, something scans it, and a result comes out.

A scan grades what it was shown. That breaks in two directions, and both of them are quiet.

The first is that the numbers people care about usually did not originate in the database. ARR, churn, bookings — those facts are born in Stripe, Salesforce, or QuickBooks. What sits in Postgres is a mirror, and a mirror is only as good as its provenance. A row carrying a subscription id the payment processor has never heard of scans identically to a real one.

The second is that the estate you were shown may not be the estate that exists. Connect three clean databases out of forty and a naive scan returns a clean result. What makes this hard is that the mechanism is identical whether the omission was deliberate, forgetful, or simply an engine the tooling cannot read — and from inside the scan, those three are indistinguishable.

Both failures are the same failure: absence read as absolution. Nothing was found, so nothing is wrong. It is the same error as a bank clearing a payment because the destination account looks unremarkable from where it happens to be standing.

What actually corroborates

Here is the sharpest version of the rule, and it is worth stating plainly: a check is only corroboration if the subject could not have produced the answer.

That disqualifies more than people expect. If software running on a company’s laptop calls its payment processor and reports what came back, the company controls the machine, the network, and the process. A locally fetched response is not evidence — it is an attestation with extra steps, and signing it afterward just signs a number the subject could have supplied.

In practice only two structures survive that test:

  • A read-only grant the subject authorizes inside the provider’s own interface, where the response is fetched somewhere the subject does not control and never transits their machine.
  • A read-only credential held by the recipient — the investor, acquirer, or auditor — who runs the check themselves.

Everything else is internal consistency. That is genuinely valuable, but it is a different thing, and it should never be counted as corroboration. What it does is make casual fabrication expensive. The cheapest strong test in the set is also the easiest to explain: real provider ids carry random suffixes, so sorting rows by id and sorting them by creation time should produce unrelated orderings. Rows minted in a single pass produce the same ordering twice.

-- Do these ids sort the same way their timestamps do?
-- Real provider ids have random suffixes, so the two orderings
-- should be uncorrelated. Near 1.0 means every row was generated
-- in one pass, not accumulated over time.
select corr(id_rank, time_rank) as id_time_correlation
from (
  select row_number() over (order by id)         as id_rank,
         row_number() over (order by created_at) as time_rank
  from subscriptions
) ranked;

A result near zero is what a real payment history looks like. A result near one means the rows arrived together no matter what their timestamps claim.

And now the honest caveat, which matters more than the test. This fires on legitimate work too. Forty thousand rows imported during a billing-provider migration look exactly like fabrication: sequential ids, uniform timestamps, no failed charges, no disputes. So does seeded demo data, and a load test that leaked into production. A signal like this should never print a verdict — it should print what it found and leave a place for the answer.

An automated check should say “unexplained,” never “fraud.” The distance between those two words is a company you have defamed.

The ingredient you cannot fake is time

The most useful line in Javelin’s report is an aside about cross-network signals: unlike static attributes, they are rooted in activity over time, which is what makes them hard to fabricate. That generalizes well beyond fraud.

A point-in-time check can be prepared for. An accumulating record cannot, because faking it means having faked it consistently for months, across every system and every colleague. That changes who does the work. Under a one-shot audit, the honest company scrambles to assemble evidence. Under an accumulating record, it clears the bar by working normally — while an evasive one has to coordinate something that looks much less like a shortcut and much more like a conspiracy.

That principle is why AddisDB’s sensitive-data scan is built the way it is: strictly read-only, never opening a write grant, and keeping no row-level data at all — for each column it records how many values it sampled and how many matched, and nothing else. That is what makes it safe to run every week for a year, and a scan you can repeat is worth far more than a perfect one run the day before diligence starts. The same idea drives ADBR, the rating we issue for the data a company runs on: every report carries two numbers rather than one — what the evidence supports, and how much of the estate could actually be seen. Its own page opens with what the rating cannot do. A rating that hides its limits is just a logo.

The takeaway

If someone hands you a database and asks you to confirm it tells the truth, the honest answer has two numbers in it: what you found, and how much you could actually see. A clean result over a scope you did not choose is not a clean bill of health — it is how a check becomes a rubber stamp. Javelin’s report is worth reading in full even if you have never worked on fraud; the link is below. Then go ask whether the data you rely on has ever been checked by someone who could not also have written it.

Sources