Initial commit: Incredigo — local-first RAM-only credential custody
v1: discover → migrate → expiry tracking → sealed export/import. - vault: memguard mlock/DONTDUMP arena, handle indirection, zeroize-on-drop - discover: registry + 8 read-only scanners (aws, env, netrc, ssh, docker, kube, git) and a file/dir harvester (--path) - sink: gopass streaming insert; length-prefixed bundle framing; Sealer interface with three impls — age (default, authenticated), hmac (authenticated, openssl-only encrypt-then-MAC), openssl (CBC fallback, unauthenticated; OpenSSL 3.x enc refuses AEAD) - policy: local expiry engine, 60d/8w threshold parser - audit: redacted append-only JSONL, injectable clock - export/import: passphrase from no-echo prompt or $INCREDIGO_PASSPHRASE into locked memory; secrets stream gopass<->Sealer as bytes, never Go strings - tests: scanner leak-checks, vault zeroize, bundle round-trip via fake gopass; go test ./... green, -race clean Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# Security model
|
||||
|
||||
incredigo's job is to *minimize the footprint and lifetime* of plaintext secrets.
|
||||
It is not a substitute for a trustworthy machine.
|
||||
|
||||
## Guarantees
|
||||
|
||||
| Threat | Mitigation |
|
||||
|---|---|
|
||||
| Plaintext leaks to disk | Never written. gopass GPG blobs or sealed bundles (age/hmac/openssl) only; no temp files. |
|
||||
| Plaintext leaks via swap | `mlock` on every secret buffer (memguard). |
|
||||
| Plaintext via core dump / process snapshot | `MADV_DONTDUMP`, guard pages, zeroize on drop; `memguard.CatchInterrupt`. |
|
||||
| Source files corrupted by the tool | Scanners are strictly read-only (`O_RDONLY`). |
|
||||
| Old cred destroyed before replacement verified | v1 deletes nothing. (v2 rotation verifies-new before revoke-old.) |
|
||||
| Secrets in logs | Audit log records only redacted metadata; identities are pre-redacted by scanners. |
|
||||
| Secrets in `ps`/argv | Secrets are piped via stdin (gopass); the backup passphrase reaches openssl over an inherited fd (`-pass fd:3`). Never argv, never env. |
|
||||
| Network exfiltration | No network calls in v1. |
|
||||
|
||||
## Honest limits
|
||||
|
||||
- incredigo cannot protect plaintext from a **compromised OS/kernel** or a malicious
|
||||
**gpg-agent** while it runs — those already see your secrets in normal use.
|
||||
- The sealed bundle's strength is its **passphrase**. Use a strong one; the KDF is
|
||||
scrypt (`age`, default) or PBKDF2 @ 600k iterations (`hmac`/`openssl`), but a weak
|
||||
passphrase is still a weak passphrase.
|
||||
- Go's runtime can in principle copy bytes during GC compaction. memguard buffers
|
||||
live outside the Go heap to avoid this; do not copy secret bytes into Go
|
||||
`string`s or heap `[]byte` that outlive immediate use. One documented exception:
|
||||
the `age` sealer's library API takes the passphrase as a `string` (the `hmac`
|
||||
sealer does not). The vaulted secrets themselves never become strings.
|
||||
|
||||
## Restoring a bundle by hand
|
||||
|
||||
If `incredigo` itself is unavailable, a bundle is recoverable with standard tools.
|
||||
The decrypted stream is the length-prefixed record format in
|
||||
`internal/sink/bundle.go` (`uint16 pathLen | path | uint32 chunkLen | chunk | …`).
|
||||
|
||||
**age (default):**
|
||||
|
||||
```sh
|
||||
age -d backup.incredigo.age > bundle.bin # prompts for the passphrase
|
||||
```
|
||||
|
||||
**hmac (`--sealer hmac`)** — verify integrity *before* decrypting:
|
||||
|
||||
```sh
|
||||
head -c 32 backup.incredigo.age > mac.bin # bundle = HMAC-SHA256(32) || ciphertext
|
||||
tail -c +33 backup.incredigo.age > ct.bin
|
||||
openssl dgst -sha256 -hmac "$PASS" -binary ct.bin | cmp - mac.bin # must match
|
||||
openssl enc -d -aes-256-ctr -pbkdf2 -iter 600000 -pass pass:"$PASS" -in ct.bin > bundle.bin
|
||||
```
|
||||
|
||||
**openssl (`--sealer openssl`, unauthenticated):**
|
||||
|
||||
```sh
|
||||
openssl enc -d -aes-256-cbc -pbkdf2 -iter 600000 -in backup.incredigo.age > bundle.bin
|
||||
```
|
||||
|
||||
## Reporting
|
||||
|
||||
Report vulnerabilities privately to the maintainer (do not open a public issue).
|
||||
Reference in New Issue
Block a user