security: close key-escrow, AAD-binding, and KDF-downgrade gaps#63
Merged
SoulNaturalist merged 1 commit intomainfrom Apr 28, 2026
Merged
Conversation
Round 2 of the security audit, focused on architectural / E2E /
malicious-backend threats from the 2026 ETH research checklist.
CRITICAL
* Server-side seed-phrase encryption (key escrow / recovery bypass)
removed. /profile/seed-phrase now rejects plaintext bodies outright
and refuses to server-decrypt legacy blobs (returns 409 with a
re-enrol hint). EncryptionService class deleted from server/utils.py
so no code path can reach SEED_PHRASE_KEY any more.
HIGH
* AES-GCM ciphertexts in the vault now bind to per-record context via
AAD ("payload:<site_hash>" / "meta:<site_hash>" / "notes:<site_hash>").
A v2: prefix tags new-format blobs; legacy v1 blobs continue to
decrypt with empty AAD for backwards compatibility. Refusing to
decrypt v2 without a context throws — no silent downgrade. This
closes the malicious-backend row-swap attack: any swap by the server
pairs a ciphertext with a different site_hash than the one that
authenticated it, and GCM tag verification fails.
MEDIUM
* Client now enforces a hard floor of 100 000 PBKDF2 iterations
(CryptoService.minAcceptableKdfIterations). A malicious server can
no longer downgrade a registering client to a trivially brute-able
iteration count. The legacy floor was chosen so existing accounts
keep unlocking; new registrations get 600 000.
Also:
* Account-level seed phrase moved to the bound 'account-seed' AAD
namespace (cryptographic domain separation from per-record blobs).
* decryptNotesSecure helper added so notes use their own AAD context.
* All call-sites (passwords_screen, password_detail_screen,
edit_password_screen) thread site_hash through to the decrypt
methods.
See docs/SECURITY_AUDIT.md "Round 2" for the full report including the
items reviewed and confirmed safe (sharing flow, emergency access,
metadata leakage budget) and follow-up work for public-key share auth.
https://claude.ai/code/session_01TnnbXj4NqgHqALLwbHP2nq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Round 2 of the security audit, focused on architectural / E2E / malicious-backend threats from the 2026 ETH research checklist.
CRITICAL
HIGH
MEDIUM
Also:
See docs/SECURITY_AUDIT.md "Round 2" for the full report including the items reviewed and confirmed safe (sharing flow, emergency access, metadata leakage budget) and follow-up work for public-key share auth.
https://claude.ai/code/session_01TnnbXj4NqgHqALLwbHP2nq