Why trust this
You should not take this page's word for anything. Everything below is either pulled from the repository at build time or stated so you can verify it yourself in one sitting.
Read the scripts. They are short on purpose.
The whole tool is 15 scripts totalling 3161 lines, most of which are comments, checks and printed explanations. They are thin wrappers around two standard tools, written to be read before they are run. Read them here.
| Script | Lines |
|---|---|
decrypt.sh | 43 |
doctor.sh | 139 |
edit.sh | 19 |
encrypt.sh | 68 |
make-guide.sh | 254 |
render.sh | 407 |
review.sh | 337 |
rotate-shares.sh | 315 |
setup.sh | 417 |
share-sheets.sh | 115 |
split-secret.sh | 60 |
test-recovery.sh | 131 |
validate.py | 356 |
validate.sh | 412 |
verify-copies.sh | 88 |
Line counts computed from the repository at build time, commit 4ac7b58. Nothing on this page is typed by hand.
No maintainer can recover a lost passphrase
There is no back door, no escrow, no reset. Fewer than two shares plus no password-manager entry means the file stays sealed forever. That is a feature: a recovery route the maintainer holds is a recovery route an attacker can take, and a company can lose. This design has neither.
Built by one person, designed so it does not need him
Recovery uses stock age, an audited and formally specified encryption format with independent implementations, and ssss, an implementation of Shamir's Secret Sharing. The printed page names those tools, not this project. If the repository and its author both vanished, the recovery instructions would still work unchanged.
The security policy, in full
This is the project's SECURITY.md, pulled at build time: how to report a vulnerability, what is defended, and what is explicitly not defended. Stated limits are a promise about honesty, and they are the part to read most carefully.
Security policy
Reporting a vulnerability
Use GitHub’s private vulnerability reporting on this repository (Security tab → “Report a vulnerability”). Please do not open a public issue for anything security-sensitive. Reports get a response within a week; fixes ship as fast as their severity deserves.
Never include real estate data in a report — no register contents,
shares, passphrases, or screenshots of any of them. Reproduce with the
example registers in examples/.
Supported versions
The latest tagged release and main. There is no backporting; the
upgrade path is always “update the scripts, re-run the tests” — your
encrypted file needs no migration to benefit from script fixes
(schema migrations are separate, documented, and validator-guided).
Threat model boundaries — what this design does and does not defend
Defended:
- A leaked ciphertext.
estate.yaml.agealone is useless without the passphrase (age scrypt passphrase encryption). - A single compromised share or holder. Any one share reveals nothing (Shamir 2-of-3, information-theoretic).
- Credential theft via the register. The register holds no credentials, and validators actively reject credential-shaped data.
- A vanished maintainer. Recovery needs only stock
age+ssss.
Explicitly NOT defended — stated so nobody relies on it:
- A compromised local machine. Setup, review, rotation, and recovery all assume an uncompromised OS and user account. While a script runs, the passphrase lives in process memory and is passed to child processes via environment variables — visible to other processes of the same user (and root) on that machine, and never protected against a keylogger. No amount of in-memory care defeats local compromise; use a trusted, full-disk-encrypted machine.
- Terminal history/scrollback. The scripts clear the screen and say so honestly: scrollback, terminal logs, and session recorders are outside their control — closing the terminal window is part of the ceremony.
- Two colluding share holders. Any two shares open the file by design. Choose holders whose collusion you would consider authorised access.
- Deleted plaintext forensics. Deleting
estate.yamlreduces exposure; it does not scrub SSDs, snapshots, or synced-folder history. The docs repeat this wherever it matters. - Printer spools. Printed share sheets warn about them; a shop printer may retain what it printed.
Two promises worth auditing
- No account credentials in the register — enforced by both
validator tiers (
scripts/validate.sh,scripts/validate.py). - No maintainer can recover a lost passphrase. There is no back door, no escrow, no reset. Fewer than two shares plus no password- manager entry means the file stays sealed forever. That is the security property working as designed — protect the shares and the password-manager entry accordingly.
SECURITY.md at 4ac7b58Repository facts
- Licence: MIT License, read from LICENSE.
- Tests: a scripted test suite runs in CI on ubuntu and macos, read from the CI workflow. Run it yourself:
tests/run-tests.sh. - Schema: the register format is standard JSON Schema (
draft 2020-12), validatable by any conforming tool without our scripts.
Each fact above is computed from the repository at build time, commit 4ac7b58. Facts that cannot be computed are left off this page rather than estimated.
And the maker
Built by Jamie Watters: 38 years in corporate technology, building open tools in public at jamiewatters.work. He has been the executor with nothing to go on; that story is here, kept separate because a reason to build something is not evidence that it works. The evidence is above.