contract-vault stores executed contracts — sensitive legal and financial data — so this document states the security model honestly: what the tool guarantees, what it does not, and how to operate it safely.
Please report privately — do not open a public issue. Use GitHub's "Report a vulnerability" (Security advisories) on the repo, or email Drbaher@gmail.com. We aim to acknowledge within a few days. The latest released minor version receives fixes.
- No network, no telemetry, no background process. contract-vault never transmits your data anywhere; there is no code path that phones home. It does not auto-push to git.
- No in-tool LLM. Extraction (and any LLM use) is delegated to
extract-cli, opt-in viaingest --llm. The register / calendar / reminder logic is fully deterministic. - Zero runtime dependencies. The installed package pulls in nothing — a minimal supply-chain surface. Releases are published via PyPI Trusted Publishing (OIDC, no long-lived token).
- No dangerous parsing/execution. JSON only — no
eval,exec,pickle, oryaml.load. All subprocess calls (git,extract) are list-form (no shell), and git paths are passed after--. - Path containment. Counterparty/title are slugified to
[a-z0-9-], so values like../../etc/passwdcannot escape the vault. - Untrusted input is not trusted with your filesystem. When you ingest piped or
.jsonextract output,document.source_pathis treated as metadata only — contract-vault will not copy an arbitrary local file into the vault. Onlyingest <doc>(a file you chose on the command line) vaults the source document. - Restrictive permissions (POSIX). The vault directory is created
0700andrecord.json/ vaulted source files0600(owner-only). On Windows, rely on ACLs. - Integrity + audit.
verifyrecomputes each vaulted source's SHA-256 and checks the git tree is clean; every change (ingest, accept, obligation, config) is an auditable git commit (history <deal>).
- The working copy is plaintext. record.json and source documents on disk are not
encrypted in the working tree. Protect them with:
- Full-disk encryption (FileVault / LUKS / BitLocker) — the primary control.
- The default owner-only permissions (above) — keep the vault off shared accounts.
- A private git remote — never push a contract vault to a public repo.
- Commits are not cryptographically signed. Integrity is covered by SHA-256 + git;
for authorship authenticity, enable
git config commit.gpgsign truein the vault.
For an encrypted-at-rest vault (so what's committed/pushed is ciphertext), initialize with:
contract-vault init ~/contracts --encrypt # requires `git-crypt` on PATH
git-crypt export-key ~/contract-vault.key # BACK THIS UP — without it, history is unrecoverableThis marks record.json and source.* as git-crypt-encrypted via .gitattributes. The
working tree stays decrypted (so the CLI works normally) — git-crypt protects the repo
and any remote, not the local working copy, so keep full-disk encryption on too. Existing
plaintext history is not retroactively encrypted; enable --encrypt on a fresh vault.
- GitHub Actions are pinned to full commit SHAs (not floating tags). This matters most
in
publish.yml, which holdsid-token: write(PyPI publishing rights) — a compromised floating action tag there could otherwise publish a malicious release. Dependabot (github-actions, weekly) keeps the pinned SHAs current. - Trusted Publishing + build attestations. Releases publish via PyPI Trusted Publishing (OIDC; no stored token) with PEP 740 attestations: true, so each artifact carries verifiable build provenance.
- Static analysis in CI: Bandit (medium+ severity) and CodeQL (security-extended)
run on every push/PR — a guard against introducing
shell=True,eval,pickle, etc. - Least-privilege workflows:
contents: readby default;id-token: writeonly on the publish job.
- Protect the
pypideployment environment (Settings → Environments →pypi→ required reviewers) so a publish needs human approval. - Branch protection on
main: require a PR, passing CI, and review (CODEOWNERS is in.github/CODEOWNERS). - Enable GitHub code scanning so CodeQL results surface in the Security tab.
- Vault on a full-disk-encrypted volume
- Private git remote only
-
contract-vault init --encrypt(git-crypt) if the repo/remote may be exposed; key backed up -
git config commit.gpgsign trueif you need signed history -
contract-vault verifyin CI/periodically to detect tampering