cipher protects secret files at rest with envelope encryption backed by SOPS. This document covers the supported versions, the disclosure process, the threat model, and key handling guidance.
Pre-1.0, only the most recent tagged release is supported. Older tags receive no fixes or backports.
| Version | Status |
|---|---|
| Latest tag | Active. |
| Older tags | Unsupported. |
Report privately through GitHub Security Advisories.
Include:
- Affected version or commit hash.
- A short reproduction.
- Observed impact and any known mitigation.
Acknowledgment target is 72 hours. A coordinated disclosure window is agreed once the report is confirmed. Public disclosure happens after a fix is released, or 90 days from the report, whichever comes first.
Do not open public issues for security reports.
| Asset | Protection |
|---|---|
| File contents on disk | Encrypted with a per-file data key wrapped by every configured backend. |
| File contents on a network | Inert ciphertext when paired with HTTPS or other transport security. |
| Recipient changes | Add or remove without re-encrypting the payload. The wrapped data key changes, the bulk payload does not. |
| Plaintext during edit | Materialized only in a private 0700 temp directory in a 0600 file, removed best-effort when the editor exits. |
| Asset | Reason |
|---|---|
| Plaintext in memory after decryption | Once Decode returns, plaintext lives in the caller's process. Memory hygiene is the caller's responsibility. |
| Decrypted temp files after a crash | cipher edit removes the temp dir best-effort. A hard crash leaves the temp file until the OS cleans /tmp. |
| Logged plaintext | If the caller logs decrypted contents, cipher cannot help. Use json:"-" on secret struct fields and zap encoders that redact. |
| Compromised backend identity | Anyone holding SOPS_AGE_KEY, a valid KMS principal, or a Vault token can decrypt every file encrypted to that recipient. Rotate after compromise. |
| Side channels | No constant-time guarantees. Pair with a cloud KMS where a hardware root of trust matters. |
| Compromised dependencies | cipher depends on SOPS, age, and cloud SDKs. A vulnerability in any of those reaches cipher. |
| The host OS, Go runtime, or filesystem | Outside cipher's perimeter. |
| Boundary | Trusted side | Untrusted side |
|---|---|---|
| KMS API call | The calling process with valid credentials. | The network in between, assumed HTTPS. |
| Encrypted file | Anyone with read access can copy it. | Without recipient credentials, plaintext stays inaccessible. |
| Editor subprocess | The user's text editor binary. | Other processes on the host that can read /tmp while the editor is open. |
| Pre-commit hook | The repo's working tree on a developer machine. | Any shell or editor path that bypasses the hook. |
- Generate age identities with
age.GenerateIdentityorage-keygen. Never derive an age secret from a passphrase or any deterministic input. - Store the age secret string with
0600permissions and load it throughSOPS_AGE_KEY_FILE, or fetch it from a secret manager at startup. - Prefer cloud KMS in production where IAM and audit logging are first class.
- Rotate the per-file data key with
cipher rotateafter every recipient removal, after personnel changes, and on a periodic schedule. - Never commit an age secret, a KMS access key, or a Vault token. Install
cipher precommitto block plaintext leaks at commit time. - Treat
--allow-orphanas a one-way door. It removes the last recipient and the file becomes undecryptable.
| Limitation | Workaround |
|---|---|
| Plaintext lifetime in memory is not bounded. | Zero buffers in the caller after use. |
| Temp file cleanup is best-effort. | Run cipher edit on a host with tmpfs for /tmp. |
Recipient identifiers passed via flags are visible to ps. |
Acceptable. Recipient strings are public-key material, not secret. |
| Logging redaction is the caller's responsibility. | Use the patterns documented in logger godoc. |
cipher does not implement cryptography. It composes:
- SOPS for envelope encryption and key-group rules.
- age for X25519 plus ChaCha20-Poly1305.
- AWS, GCP, Azure, and Vault SDKs for managed-key envelope wrapping.
Algorithm parameters follow the defaults of each backend. Propose algorithm upgrades through the regular issue tracker, not this disclosure path.
Track this file in git. Material changes get a SECURITY.md commit and a corresponding entry in the release notes for that tag.