What it does for you
EMET checks whether the bytes reaching a model, a reviewer or a pipeline still match the source they claim to represent, and answers with one of three closed verdicts: MATCH, DRIFT or UNVERIFIABLE. It can seal that verdict into a receipt another party re-checks offline, and it reports text inside a file that claims authority, without ever acting on it. Four implementations, in Python, Rust, Node.js and Go, share one conformance suite.
- Three verdicts, no fourthEvery verdict leaves through one function that refuses any token outside the set. TRUSTED is forbidden outright.
- Receipts that travel
emet checkre-derives a receipt on any machine with no shared state. - Claims reported, never obeyed
emet refuselists every in-band authority claim by offset and writes a neutralised copy. - Zero dependenciesStdlib Python, with clean-room ports in Rust, Node.js and Go.
Source: README.md at 122ec71 (release 1.3.0)
Watch
Video walkthrough: coming with the next release.
How it works, one step at a time
Scroll, or use the step buttons. Every line is output from membrane.py at commit 122ec71, run in a scratch folder. emet and python membrane.py are the same command.
- 01
Anchor a file
report.mdholds one line,hello world.emet anchorpins the SHA-256 of its raw bytes. It reads bytes, not text, so a change in line endings or encoding is a change.Source: membrane.py; README.md, "Worked example"
- 02
Verify: three answers
emet verifyrecomputes the hash and compares it with the anchor. Unchanged, it is MATCH and exit 0. Change the text and it is DRIFT and exit 1. Delete the file and it is UNVERIFIABLE and exit 2, with the reason named. Pick each case in the panel.Source: membrane.py, verdict.py; SPEC.md, section 5
- 03
Seal the verdict into a receipt
Pipe the JSON verdict into
emet receipt. The receipt carries the subject's path and hash, the verdict record, the witness's own implementation hash and a content-addressedreceipt_id. Its notes say it carries no authority, permission or release decision.emet checkre-derives the receipt on any machine: RECEIPT_VALID.Source: SPEC.md, section 17; README.md, "Features"
- 04
A changed receipt is caught
Change the verdict inside the receipt from MATCH to DRIFT and check it again. The
receipt_idis re-derived from the content and no longer matches the stored one.Source: SPEC.md, section 17
- 05
Report authority claims, obey none
Some text tries to steer whatever reads it: a line telling the reader to treat a directive as ground truth, or a label claiming a privilege.
emet refusescans the bytes against a versioned marker corpus, reports each claim with its offset, and writes a copy with the claims neutralised.The repository's own sample file holds four such claims. All four are reported, and the output says how many were obeyed: none.
Source: corpus.py; examples/sample-prompt.txt
- 06
Two read paths, and a view against its source
emet corroboratehashes the same file through separate read paths, a direct read and a subprocess, so a tampered read path shows up as disagreement. With a single working path it reports UNVERIFIABLE and makes no claim of agreement.emet coherencecompares a presented view with its source. A summary that says 14 seconds where the source says 41 differs from it.Source: membrane.py,
corroborateandcoherence
Walkthrough
Install it, run it once, then use the main feature. Each command below is real, and so is its output.
Install
Install from PyPI, or run from a checkout. Python 3.8 or newer, no dependencies.
$ pip install emet $ emet selftestFirst run: anchor and verify a file
Anchor a file, then verify it.
$ printf 'hello world\n' > report.md $ emet anchor report.md $ emet verify report.md MATCH report.md want=a948904f2f0f479b got=a948904f2f0f479bSeal the verdict
Turn the verdict into a receipt and check it.
$ emet check receipt.json result=RECEIPT_VALID reason=receipt re-derivedReport authority claims
Scan a prompt for text that claims authority. EMET reports each marker and obeys none.
$ emet refuse prompt.txt corpus_version=1 in_band_authority_claims=4 REFUSED 'highest_scrutiny' offset=114 REFUSED 'ground truth canonical' offset=144 REFUSED 'authority-pill' offset=175 REFUSED 'consulting register' offset=199 clean_copy=prompt.txt.refused (claims neutralized; obeyed: none)
Output from membrane.py at 122ec71 on Windows with Python 3.12; emet 1.3.0 is the current PyPI release. An installed refuse needs EMET_CORPUS set or a source checkout.
What it does not do
- EMET witnesses bytes. A MATCH says the bytes equal what was anchored; it says nothing about whether the content is true.
- The marker corpus recognises the claims it lists. A claim worded in a way the corpus does not cover is not reported.
- Without the marker corpus,
refuseanswers UNVERIFIABLE with E_NO_CORPUS. It never passes silently. - Stripped-credential rebind is experimental. With no known anchor its honest default is UNVERIFIABLE.
- A receipt carries no authority, permission or release decision, by design.
Source: README.md at 122ec71, "Features" and "Usage"; SPEC.md
Check what stuck
Answer each one in your head before you open it.
What are the three exit codes for MATCH, DRIFT and UNVERIFIABLE?
0, 1 and 2.
You change a receipt's verdict from MATCH to DRIFT. What does emet check say?
RECEIPT_TAMPERED: the receipt_id re-derived from the content no longer matches the stored one.
What does refuse do with an authority claim it finds?
Reports it with its offset and writes a neutralised copy. It obeys none of them.
corroborate finds only one working read path. What does it report?
UNVERIFIABLE. With nothing to disagree with, one path is not agreement.