fix: decrypt SOPS through explicit custody into private output
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a12d13-27f2-7163-b8c0-f682af02772c
This commit is contained in:
parent
4cf26a9bc8
commit
681c5b0ea1
6 changed files with 499 additions and 27 deletions
|
|
@ -174,8 +174,53 @@ its trap while a foreground child runs; this is not a process-group supervisor,
|
|||
SIGKILL cleanup guarantee or a runtime authority boundary. Temporary key cleanup
|
||||
on command return does not certify that an arbitrary child retained no copies.
|
||||
|
||||
Remaining concrete caller defects stay in NK-WP-0049-T02: Make `sops-setup` /
|
||||
`creds-init` still install or require permanent HOME keys; Make `sops-decrypt`
|
||||
still emits plaintext; legacy rotation and privacyIDEA bootstrap helpers contain
|
||||
secret-bearing output. Do not use those legacy paths as the recovery procedure
|
||||
Remaining concrete caller defects stay in NK-WP-0049-T02: legacy rotation and
|
||||
privacyIDEA bootstrap helpers contain secret-bearing output; direct editor,
|
||||
rotate and delegated apply/init paths still need their own custody/output audit. Do not use those legacy paths as the recovery procedure
|
||||
or treat these narrower helper repairs as closure of the whole custody surface.
|
||||
|
||||
## Make recovery entry points — 2026-10-12
|
||||
|
||||
`make sops-setup` now validates only `keys/age.pub`. It never copies or generates
|
||||
a private key; `creds-init` likewise has no permanent HOME key requirement.
|
||||
Existing permanent files are not deleted or represented as remediated copies.
|
||||
|
||||
`make sops-decrypt FILE=... OUTPUT=...` requires the custody helper's explicit
|
||||
`NETKINGDOM_CUSTODY_AGE_KEY_FILE`. The owned private regular key file must match
|
||||
the registered public recipient. Output must be a new file in an owned private
|
||||
parent outside Git worktrees (including linked-worktree markers and bare repos).
|
||||
No destination file/symlink is overwritten. Partial tool output is removed on
|
||||
failure; successful publication is atomic and mode 0600. The operator removes
|
||||
successful plaintext after the approved operation. This does not promise cleanup
|
||||
after SIGKILL, hostile same-UID interference or arbitrary child copies.
|
||||
|
||||
For the repository's age custody profile, the wrapper accepts SOPS JSON/YAML,
|
||||
and rejects non-age recipients, age plugins, key groups, unknown metadata and
|
||||
duplicate keys before decryption.
|
||||
Other formats/backends require their own reviewed adapter; they are not silently
|
||||
sent through a different credential source. YAML input requires PyYAML.
|
||||
|
||||
SOPS runs with an isolated HOME/XDG configuration and a minimal environment,
|
||||
using an inherited descriptor for the explicit key. This prevents SOPS from
|
||||
combining it with HOME/SSH keys, inline keys, key commands, proxies or remote key
|
||||
services. Raw parser/tool diagnostics and plaintext stdout never enter the
|
||||
terminal transcript. This wrapper assumes trusted installed `age`, `age-keygen`
|
||||
and `sops` binaries; it is not an OS sandbox or task-authorization grant.
|
||||
|
||||
Use from the operator's approved custody terminal, with a private directory
|
||||
created outside all repositories (for example using `mktemp -d`):
|
||||
|
||||
```bash
|
||||
# OUTPUT's parent must exist and be owned/private; select a new filename.
|
||||
make sops-custody-run COMMAND='make sops-decrypt FILE=secrets/example.yaml OUTPUT=/private/recovery/new-example.yaml'
|
||||
```
|
||||
|
||||
The command string carries paths only. Never put a credential in FILE, OUTPUT,
|
||||
COMMAND, shell history or Make variables. Tests exercise real SOPS 3.13.3 with
|
||||
disposable keys; no production key or encrypted secret was accessed. The test
|
||||
binary checksum was checked against the official release checksum; no detached
|
||||
signature verification or installed-toolchain promotion is claimed.
|
||||
|
||||
Source basis: [SOPS age identity loading](https://github.com/getsops/sops/blob/v3.13.3/age/keysource.go)
|
||||
loads explicit and ambient identities together, so setting `SOPS_AGE_KEY_FILE`
|
||||
alone is insufficient to exclude ambient credentials.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue