fix: validate-before-mutate in recipients add/rm + verify messaging + doc/UX polish (EGB-283)
- Fix 1 (IMPORTANT): _recipients_rm and _recipients_add now call _load_recipients BEFORE any mutation. A hand-corrupted recipients.txt dies at validation, leaving the file untouched — prevents inconsistent state where the file is changed but blobs are not re-encrypted. On a legacy store (no recipients.txt), _load_recipients succeeds via the derived-pubkey path so the bootstrap path still works. - Fix 2 (MINOR): Guard _check_blob_recipient_count behind a successful decrypt in both _verify_all and _verify_project — an undecryptable blob no longer produces a spurious "encrypted to 0 recipients" finding. Reword _verify_all summary to "failed (decrypt or recipient-count)" since both failure modes now increment the counter. - Fix 3 (MINOR): Correct README offboarding comment from "New blobs are no longer readable" (contradicts the re-encrypt of EVERY blob) to "Existing blobs are re-encrypted; the removed key can no longer decrypt them." - Fix 4 (MINOR): cmd_reencrypt prints an advisory when no recipients.txt exists (single-key store), so the operator knows they can add teammates. - Fix 5 (MINOR): Test coverage for ambiguous-name rm refusing to remove when multiple recipients share a --name label. Tests: 5 new tests in test/recipients.bats (34 total, all pass). Full suite 276 tests: 5 known pre-existing failures (3 mode-600/stat, 2 jq-PATH), none new. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f7576a3eae
commit
17772dfec6
3 changed files with 84 additions and 11 deletions
|
|
@ -341,6 +341,59 @@ make_second_identity() {
|
|||
[[ "$output" == *"valid age recipient"* ]] || false
|
||||
}
|
||||
|
||||
# ── Fix 1: validate-before-mutate ────────────────────────────────────────────
|
||||
|
||||
@test "recipients rm dies without mutating a hand-corrupted recipients.txt" {
|
||||
init_with_remote
|
||||
make_second_identity
|
||||
run "$SECRETS_BIN" recipients add "$BOB_PUB" --name bob # valid: self + bob
|
||||
# Corrupt the file by hand.
|
||||
printf 'age1-not-a-valid-key\n' >> "$SECRETS_DIR/recipients.txt"
|
||||
before=$(cat "$SECRETS_DIR/recipients.txt")
|
||||
run "$SECRETS_BIN" recipients rm bob
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "$output" == *"Invalid recipient"* ]] || false
|
||||
# File unchanged (no half-mutation).
|
||||
[ "$(cat "$SECRETS_DIR/recipients.txt")" = "$before" ]
|
||||
}
|
||||
|
||||
@test "recipients add dies without mutating a hand-corrupted recipients.txt" {
|
||||
init_with_remote
|
||||
make_second_identity
|
||||
printf 'age1-not-a-valid-key\n' >> "$SECRETS_DIR/recipients.txt" # init seeded self; now corrupt
|
||||
before=$(cat "$SECRETS_DIR/recipients.txt")
|
||||
run "$SECRETS_BIN" recipients add "$BOB_PUB" --name bob
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "$output" == *"Invalid recipient"* ]] || false
|
||||
[ "$(cat "$SECRETS_DIR/recipients.txt")" = "$before" ]
|
||||
}
|
||||
|
||||
# ── Fix 4: reencrypt advisory on a legacy store ───────────────────────────────
|
||||
|
||||
@test "reencrypt on a legacy store prints a single-key advisory" {
|
||||
init_with_remote
|
||||
rm -f "$SECRETS_DIR/recipients.txt"
|
||||
create_project_dir myproj
|
||||
run "$SECRETS_BIN" push
|
||||
run "$SECRETS_BIN" reencrypt
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"single-key"* ]] || false
|
||||
}
|
||||
|
||||
# ── Fix 5: ambiguous-name rm coverage ────────────────────────────────────────
|
||||
|
||||
@test "recipients rm by an ambiguous name is refused" {
|
||||
init_with_remote
|
||||
make_second_identity
|
||||
age-keygen -o "$TEST_TMPDIR/carol.txt" 2>/dev/null
|
||||
CAROL_PUB=$(age-keygen -y "$TEST_TMPDIR/carol.txt")
|
||||
run "$SECRETS_BIN" recipients add "$BOB_PUB" --name dup
|
||||
run "$SECRETS_BIN" recipients add "$CAROL_PUB" --name dup
|
||||
run "$SECRETS_BIN" recipients rm dup
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "$output" == *"matches"* ]] || false
|
||||
}
|
||||
|
||||
@test "SECURITY: a symlinked recipients.txt is refused on add and rm too" {
|
||||
init_with_remote
|
||||
make_second_identity
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue