Skip to content

Kritolith

Verify, dedupe, reproduce.

Kritolith checks incoming security reports before a maintainer reads them.
It tests every claim against the real code, reproduces the PoC in a locked-down sandbox,
flags duplicates, and hands you a signed evidence verdict.

License: Apache-2.0 Status: pre-alpha Go Self-hosted PRs welcome

How it works · Verdicts · Scope · Roadmap · Contributing · Security

Warning

Kritolith is pre-alpha and under active development. The commands below show the planned interface and don't work yet. Don't run it on real embargoed reports until sandbox hardening lands.


Why

Maintainers are buried in security reports. Many cite files or functions that don't exist, many are duplicates of each other, and refuting a single fake one can take hours. The harder problem now is volume: too many credible-looking reports and not enough maintainer time.

Kritolith does the tedious first pass so you only spend time on reports that survived it. It never makes the decision for you. Every verdict comes with the evidence behind it, and humans decide what happens next.

How it works

flowchart LR
    A["📥 Intake<br/>GitHub private reports<br/>.eml · CLI"] --> B["🔎 Extract<br/>files, functions,<br/>lines, versions"]
    B --> C["🌳 Ground<br/>check claims against<br/>git at the claimed ref"]
    C --> D["🧬 Dedupe<br/>past reports +<br/>OSV mirror"]
    D --> E["📦 Sandbox<br/>gVisor · no network<br/>claimed ref + HEAD"]
    E --> F["✍️ Verdict<br/>evidence bundle,<br/>ed25519 signed"]
Loading
Stage What it does
Intake Receives reports from GitHub private vulnerability reporting, piped .eml messages, or a local file.
Extract Pulls out concrete claims: file paths, pkg.Func names, file.go:123 lines, versions, commit SHAs, PoC code. Deterministic parsing first; an optional LLM fills gaps with strictly validated JSON.
Ground Checks out the claimed commit and verifies each claim with git and Go's own parser. Does http2.parseHeader actually exist at a3f9c1?
Dedupe Compares against earlier reports (fingerprints + embeddings) and a local mirror of the OSV Go advisory database.
Sandbox Builds and runs the PoC under gVisor with no network, hard CPU/memory/PID limits, and a control run at HEAD.
Verdict Writes a short, factual verdict plus an evidence bundle signed with ed25519, so anyone can check it wasn't altered.

Example verdict

Kritolith: GROUNDING_FAILED at a3f9c1
• function http2.parseHeader — not found (closest: parseHeaders, frame.go:412)
• file internal/hpack/decode.go — found
PoC not run: grounding failed on a hard claim.
Evidence bundle: sha256:… (signed)

Verdicts

Outcome Meaning
🟥 REPRODUCED The PoC triggered the claimed behavior at the claimed commit.
🟧 REPRODUCED_FIXED_AT_HEAD Reproduces at the claimed commit but not at HEAD. Probably already fixed.
⬜ NOT_REPRODUCED The PoC ran cleanly and the claimed behavior was not observed.
🟪 GROUNDING_FAILED A hard claim (a file or function) provably doesn't exist at the claimed commit.
🟦 LIKELY_DUPLICATE Strong match to an earlier report or a published advisory. Shown alongside the repro result.
🟨 NEEDS_INFO No runnable PoC, or no identifiable commit or version.
⬛ INCONCLUSIVE Build failure, timeout, sandbox error, or anything ambiguous.

Important

Kritolith is built never to wrongly reject a real report. Line numbers drift, so a wrong line alone never causes GROUNDING_FAILED. When the evidence is unclear, the answer is INCONCLUSIVE, not a rejection.

Design principles

  • Deterministic checks decide. The LLM only extracts claims and drafts replies. Everything it produces is re-verified against git or the sandbox.
  • Every report is hostile input. Report text, PoC code and attachments are assumed to contain prompt injection or sandbox escape attempts.
  • Evidence, not opinions. Each claim records what was found, where, and at which commit.
  • One static binary. Standard library first. The only third-party Go module is a pure-Go SQLite driver. No vendor SDKs.

Privacy and LLMs

Security reports describe unfixed vulnerabilities, so Kritolith is local-first:

  • It works with no LLM at all, using deterministic extraction only.
  • It supports local models through any OpenAI-compatible server: Ollama, llama.cpp, vLLM, LM Studio.
  • Cloud providers (OpenAI, Anthropic, Gemini) are an explicit per-project opt-in, and every cloud call is logged with the report ID.
  • No telemetry. Report content never appears in logs above debug level.

Planned usage

Check a report from the command line
kritolith check --repo owner/name --ref a3f9c1 report.md --poc ./poc/
Run as a service for GitHub private vulnerability reports
kritolith keygen        # create the ed25519 signing key
kritolith osv sync      # build the local OSV mirror
kritolith serve         # webhook server + workers

Verdicts are emailed to the project's configured maintainers and stored locally. GitHub has no API for commenting on advisories.

Pipe in reports from email
kritolith ingest --eml < message.eml

Works with fetchmail, procmail, a Postfix pipe, or anything else that can hand over a raw message.

Verify a signed evidence bundle
kritolith verify-bundle verdict-01J9Z….tar

Requirements: Linux with gVisor (runsc), git, and the Go toolchain. An LLM is optional.

Scope

Version 1 deliberately stays narrow.

✅ In v1 🚫 Not in v1
Go projects Other languages
GitHub private reports, .eml, CLI intake HackerOne / Bugcrowd integrations, IMAP
Grounding, dedupe, sandbox repro LLM-based exploitability scoring
Signed evidence verdicts CSAF / VEX / CRA reporting
Self-hosted single binary Web dashboard, hosted multi-tenant service

Roadmap

  • Skeleton: core types, SQLite store, kritolith check end to end
  • Claim extraction + pluggable local-first LLM layer
  • Grounding against git and the Go AST
  • Deduplication with embeddings and a local OSV mirror
  • gVisor sandbox with hostile-PoC hardening
  • Signed verdicts, email delivery, .eml intake
  • Public threat model, install docs, first release

Progress is measured on a public eval corpus of real Go advisories and deliberately fabricated reports. The v1 bar:

Target Goal
Real reports wrongly marked GROUNDING_FAILED 0
Fabricated reports with fake code caught by grounding ≥ 80%
Real reports with runnable PoCs reproduced ≥ 60%
Duplicate top-1 accuracy ≥ 80%

Contributing

Contributions are welcome, and fabricated test reports for the eval corpus are especially useful. Read CONTRIBUTING.md first. All commits need a DCO sign-off (git commit -s).

This project follows the Contributor Covenant.

Security

Found a vulnerability in Kritolith itself? Don't open a public issue. Please report it privately. See SECURITY.md.

License

Apache License 2.0

About

Verifies security reports before maintainers read them. Checks every claim against the code, reproduces PoCs in a sandbox, and flags duplicates. Self-hosted, local-LLM first.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages