Public proof

Evidence you can inspect. Misses included.

Open the requirements, findings, reproducers, fixes, withdrawals, and misses from real public audits. Run the evidence yourself.

01 · One finding, end to end

Start with one finding. Run it yourself.

Before any roster or any count, here is a single finding from the jsonparser audit with every record it left behind. Each step is a file on the public master branch of buger/jsonparser, and each link goes to that file. The command that re-runs the whole thing is at the foot of this section.

PUBLIC AUDIT EVIDENCE Every link in this section, and every link in the run-it-yourself card below it, opens a file on the public master branch of buger/jsonparser.

  1. 01

    RequirementSYS-REQ-009status: approved

    Set() replaces the addressed value, creates a type-consistent path, or returns KeyPathNotFoundError.

    A person who owns the code approved that sentence before any code was judged against it. Until a requirement is approved it stays a candidate and nothing is measured against it.

    specs/system/requirements/SYS-REQ-009.req.yaml

  2. 02

    Known issueKI-3was violated

    An array-index path component under an object parent produced malformed JSON, and Set() returned it with a nil error.

    The caller had no signal that the bytes could not be parsed again. A known issue stays open until its closure is verified, and the register says which state it is in. This one now reads status: fixed.

    proof/known-issues/KI-3.yaml

  3. 03

    Reproducerset_spec_test.goexecutable

    One test file carries // Verifies: SYS-REQ-009 and // Reproduces: KI-3 (fixed) on one screen.

    That pair is the join the rest of the chain hangs on: the same file says which promise it proves and which failure it pins.

    set_spec_test.go · TestSetArrayIndexUnderObjectMalformedJSON_KI3

  4. 04

    Affected revisionparser.gointroduced_in: inception

    The record names the code that carried the defect and dates it to the library’s first release.

    So every revision before the fix is affected, and the requirement’s own history stamps the window: verification failing on 26 July 2026, passing again the next morning.

    parser.go · createInsertComponent

  5. 05

    Fixing changeparser.go · Seton master

    Set() now replaces a mismatched container with the type the path expects, so every call that returns a nil error returns valid JSON.

    The annotation above func Set lists every requirement that function carries, SYS-REQ-009 first. It lives in the source, so it moves when the code moves.

    parser.go#L1394-L1395

  6. 06

    Regression evidenceproof/evidence/passing

    The same test as step 03, still in the suite, flipped at the fix: it now asserts that every cross-type call returns valid JSON.

    While the defect was live that test asserted the bug and pinned the output as malformed. A regression trips it either way. It was never red and then green, and saying so would have been the easier story.

    proof/evidence/ · ki3-set-array-index-under-object.yaml

  7. 07

    Verified defect recordDEFECT-260726-MFPAfixed

    Set with array-index path component under an object parent produces malformed JSON output.

    That is the record’s own title. Underneath it: what was expected, what happened, the root cause, the severity with its basis, the reproducer, and the retest. The requirement that opened the chain is the requirement that closes it.

    proof/problem-reports/DEFECT-260726-MFPA.yaml

Run it yourself · buger/jsonparser · master Passes

Clone the repository

git clone https://github.com/buger/jsonparser

cd jsonparser

Run the reproducer

go test -run TestSetArrayIndexUnderObjectMalformedJSON_KI3

What you should see

ok  github.com/buger/jsonparser

It passes because the fix is on master. The command needs Go and nothing else: no account, no token, no portal.

That is one finding. The rest of this page is the same material at scale: two public audit boards, the wider roster, and what none of it proves.

02 · The rsync board

The full rsync board is public.

rsync is widely shipped across Linux and Unix systems and has moved the world’s files since 1996. Proof audited it continuously through the development of its 3.5.0 security release, and the audit is still running. The whole board is published, including the entries the audit took back.

PUBLIC AUDIT EVIDENCE The board below and the release notes it links are both public records. The audit is still running, so the counts are a dated reading: 30 August 2026.

99 findings filed45 open21 fixed28 withdrawn5 re-examined and allowed to stand

The audit filed 99 findings. The 3.5.0 release shipped 33 security fixes from the combined focused audit, daemon fuzzing, Trail of Bits work, and other external research. This audit’s share is credited upstream: the rsync 3.5.0 release notes name Leonid Bugaev in their thanks and again as the reporter on individual fix entries.

The number to look at on that board is 28. Those are findings this audit filed and then disproved with its own evidence, so the board got smaller as the work went on. Five more were re-examined by a person and allowed to stand. Ten of the findings had been in the code since rsync’s first release in 1996.

Filed
Raised against the 3.5.0 development line and formalized into executable tripwires, re-run on every upstream change. The standing rule holds here: no reproducer, no finding.
Withdrawn
The audit disproved its own finding. The entry stays on the board with the reason, because a register that only ever grows has been edited.
Re-examined
A person looked at the finding again and let it stand. Re-examination is its own state on the board, so a second look leaves a record of itself.
Fixed
Closed upstream with public evidence. These 21 are this audit’s own findings. The release’s 33 security fixes are the wider set, each with its own entry in the rsync release notes; the cycle carries 39 CVE IDs in all.
Open
Filed and unresolved. Reports still moving through the upstream process are counted here, and their details stay unpublished until they are public and closed.

03 · The jsonparser record

The jsonparser misses sit beside the wins.

jsonparser is a decade-old Go library maintained by Proof’s founder. Grafana Loki, Keybase, Coroot and the Solana Go SDK each require it in a public go.mod. We ran the audit we sell against it, in public, on code we could not hide from. Two defects escaped the review anyway, and the postmortem for both sits on the project’s master branch.

PUBLIC AUDIT EVIDENCE Every link in this section opens a file on the public master branch of buger/jsonparser. The counts were read off master on 30 August 2026, and none of them comes from the seeded demo branch.

123 requirements6 found by the review2 misses published8 defect records3 change records

Those counts are an index to the artifacts, and each one is a directory or a document you can count yourself. proof/problem-reports/ on master holds eight defect files. There is no status: field to read on them; each carries a disposition block naming the requirement or known issue that now covers it, and the regression test that holds it closed — seven of them under evidence.verified_by, the eighth through KI-4, which carries status: fixed and the command that reproduces it. Two of the eight were reported by outside contributors and credited by name in the changelog, which leaves six the review found itself. Those same two are the two published misses.

Both misses were in Set(). Asked to write 9 at index [5] of the array [1,2], it handed back [9]: no panic, valid JSON, the rest of the data gone. Asked to write at the path "a" then "", it panicked. Both are fixed on master, so both examples now behave; the reproducers stay in the tree and trip if either ever returns. The affected code carried 100% MC/DC at the time, so every condition in the decision logic we checked was exercised. Exercised is a weaker property than correct.

“MC/DC has no notion of ‘correct’; it has only ‘exercised.’”

The postmortem’s own words, in docs/proof-gap-root-cause.md on master. Both defects predate the audit by years, so writing them was not the failure. Certifying around them was. That is why they count as misses and why they get a postmortem.

  • The postmortem

    Blameless, dated, six sections including a remediation table, on the public master branch beside the fixes.

  • The corpus

    All 123 requirements: 7 stakeholder promises and 116 system clauses, plain YAML. 28 carry status: approved and the remaining 95 carry status: review — and nothing is judged against a requirement until it is approved, so the file tells you which is which.

  • The reproducer

    The test file from the chain above, carrying the requirement it proves and the issue it pins. Clone the repository and run it.

Not everything on master is a defect. proof/changes/ holds three change records, and none of them is a bug. The v1.5.0 release is CHG-260728-H6ER, type: feature. It states the intent of the release and names the two requirements the release introduced, SYS-REQ-115 and SYS-REQ-116, both since approved. A feature leaves the same record a fix does, so the corpus describes the software as it ships, not as it stood on audit day.

04 · The wider roster

Our open-source security work.

Beyond the two audits above, every card here is public: a merged fix, a public pull request, or a public issue you can open, from security work we did on the open-source software the world runs on and reported upstream. Open a card to read that project’s findings and their evidence.

The credit rule

Every finding on this register was reported by Proof, from a dated report that predates the fix. What varies is whether the upstream public record names us. A report routed through a vendor’s private security channel usually leaves no public trace, so each entry says what you can confirm from the public record and what rests on our own dated files.

Every row inside a card carries one of three labels. Credited upstream: the public issue, pull request, advisory or release note names the report, or the filing is our own. Not credited upstream: the fix is public and our dated report predates it, and the upstream record does not name us. This is the normal outcome for anything reported through a vendor’s security process. Credited to another reporter: an upstream advisory names someone else for the same class. We publish ours and say so. Most rows here are not credited upstream, because most of this work went in through a vendor’s channel.

PUBLIC AUDIT EVIDENCE Every evidence link inside a card opens the vendor’s own public pull request, issue or advisory. The card counts say how many findings; the label on each row says whether the upstream record names us.

The public register lists every finding across engagements, entry by entry. Open the public register →

Some of these fixes landed as the vendor’s own pull requests; some carry a credit to us by name in the upstream record, as on rsync; on some the credit went elsewhere. Every one of them was reported by Proof. The label on each row says what the public record shows, so it travels with the row rather than being averaged away by the count on the card. Unpatched reports with nothing public yet, and anything we reported privately, are not shown here. Every row was checked against its public record on 30 August 2026.

05 · Read the labels

Three public surfaces. Three different jobs.

Proof publishes in three places, and they are not interchangeable. One of them is a product demonstration and carries seeded data on purpose. The other two are the record. Every badge below says which is which, and the same badges travel with the screenshots on the rest of this site.

SEEDED PRODUCT DEMO The branch link in the next paragraph, and every portal link on this site, point at deliberately broken demonstration data. Nothing read off that branch is an audit result.

The live portal runs on proof-demo, a showcase branch on our probelabs/jsonparser fork. That branch carries seeded demonstration issues next to the real history so the interface has a defect queue to render, and each seeded entry says so on its own page. The campaign’s real findings sit under Fixed. If you open the portal expecting a live defect queue, the open entries there will mislead you. The register and the case studies carry no seeded entries at all, and their counts are read off master.

What this record does not prove.

The limits are part of the claim, so they are published with it.

  1. The subjects were self-selected.

    We chose rsync and jsonparser, and jsonparser is maintained by Proof’s founder. Recovering intent from code you already know is the easiest version of the job, and a self-selected subject is a weaker claim than an assigned one.

  2. The product demonstration is seeded.

    The open findings on the public dashboard are demonstration entries on the showcase branch, deliberately left broken so the interface has something to show. Any count read off that branch is a demonstration count. It is not an audit result.

  3. Two audits are not a distribution.

    rsync and jsonparser are the only two projects taken through a full public audit, one in C and one in Go. The other roster entries are narrower security work, reported upstream and fixed. Two audits show what the method produced twice, with the evidence attached. They do not establish a rate at which it finds things.

  4. The private half is absent.

    Unpatched reports, findings still moving through a vendor’s disclosure process, and everything from client engagements appear on no public page here. What you can read is the resolved and public part, which is the part that can be checked.

06 · The bar

The bar is public too.

The standard this work is judged against is published in full, and it is written to survive a hostile reading. It is not summarised here, because a summary of a bar is not a bar. Four documents, four jobs.

  • Methodology

    What “verified” means, clause by clause, and the check that enforces each clause.

  • Instruments

    The machinery that turns intent into executable evidence, and what each instrument can and cannot decide.

  • Trust

    Access, disclosure, data handling, and the answers security, legal and procurement ask for.

  • Findings register

    The formal dated record, misses first: scope, findings, withdrawals, validators and evidence.

No reproducer, no finding.

A finding you cannot re-run is an opinion with formatting. A person validates every finding before it reaches you, and the reproducer is what you check both of us against.

07 · Standing offer

Apply for an open-source audit.

One open-source pre-release audit each week, self-funded, coordinated with the maintainers and run on their schedule. No invoice, and no commercial follow-up.

This record has to earn the right to be believed, and open source is the only place it can. Proof does not publish private customer corpora, even for marketing, because the requirement graph can describe the product almost as completely as the source itself. So the public record grows one self-funded open-source audit at a time, and paying our own way keeps the entries free of anyone's release marketing.

Maintainers, apply with the repository and what worries you most about it. If a release is coming, say when.

  • The map of the promises we recover, joined to the code that carries them and the tests that check them.
  • The findings, each one validated by a person before it reaches you.
  • Each finding carries a test you can run, and the record carries the command that runs it. Run them yourself. Keep them in your suite.

A person validates every finding before it reaches you.