GhostPass est zero-knowledge : le serveur ne stocke que des blobs chiffrés et ne peut déchiffrer aucun coffre. Le mot de passe maître n'atteint jamais le serveur. La cible de sécurité inclut un serveur actif/malveillant (hypothèse forte d'un password manager).
Double revue adversariale (cœur crypto Rust + backend). Bilan : invariant zero-knowledge préservé, primitives saines (XChaCha20-Poly1305, HKDF, tokens 256 bits, SQL paramétré, pas d'IDOR). Les faiblesses portaient sur le durcissement et la résistance au serveur actif.
- Anti-downgrade KDF : les
KdfParamsreçus du serveur sont validés côté client (KdfParams::ensure_strong, planchers 64 Mio / 3 passes) avant toute dérivation. - Hygiène mémoire :
Zeroizingétendu à tous les secrets transitoires (master key, clés dérivées, item keys, clé de récupération, payloads en clair). - Dépendance
subtleinutilisée retirée. - Rate-limiting global (
@fastify/rate-limit), helmet, CORS configurable, bodyLimit (anti-DoS). - Anti-énumération par timing : scrypt « à vide » exécuté quand le compte est inconnu (login et recover).
- Révocation de session : endpoint
POST /api/auth/logout. - Anti-rejeu TOTP : compteur de période consommé (login & disable) ; fenêtre ±1.
- Secret TOTP chiffré au repos (AES-256-GCM, clé serveur
MFA_SECRET_KEY, 12-factor) depuis le 2026-08-30. Hors périmètre zero-knowledge — le serveur DOIT lire cette graine pour vérifier un code — mais une fuite de base seule ne donne plus les codes 2FA de tous les comptes. La clé est facultative : sans elle le serveur démarre et l'écrit à chaque démarrage, plutôt que de refuser de tourner et de mettre dehors une instance auto-hébergée qui monte de version. - Opérations 2FA sensibles (
setup,disable) re-authentifiées par mot de passe. recovery-blobuniformisé (réponse leurre déterministe → pas d'énumération).- Email normalisé côté serveur ; détails d'erreur zod non exposés ; error-handler générique ; logger activé.
Ces points concernent le modèle multi-parties et seront traités dans la conception du partage :
- Authenticité de la distribution d'Org Key : le
sealed boxX25519 est anonyme ; un serveur actif pourrait substituer une Org Key. ⇒ signer la distribution de clés. - Révocation réelle : la rotation d'Org Key ré-enveloppe les item keys mais ne re-protège pas les secrets déjà exposés à un membre révoqué. ⇒ rotation des secrets eux-mêmes + documentation honnête de la garantie.
Second audit (cœur Rust + WASM + backend + SPA), après l'ajout du proxy de favicons, du registre
de dossiers chiffré, de la corbeille, du TOTP client, du générateur, de l'import CSV et des
notes/cartes. Bilan : invariant zero-knowledge préservé, aucun finding critique. Primitives
saines, SQL paramétré, cloisonnement user_id systématique (corbeille incluse), pas d'IDOR ni
d'injection exploitable, pas de XSS (Svelte échappe ; aucun {@html}).
- SSRF par DNS-rebinding (TOCTOU) du proxy favicons : le fetch passe désormais par
node:httpsavec unlookupvalidant — l'IP utilisée pour la connexion est exactement celle validée (rejet privé/loopback/link-local), revalidée à chaque redirection, IP littérale refusée même après redirect. Fin de la fenêtre validation≠connexion. - Cap mémoire du favicon : lecture en streaming abandonnée dès
MAX_BYTES(un serveur omettantContent-Lengthne peut plus gonfler la mémoire). - Anti-downgrade KDF déplacé dans
derive_master_key(chokepoint unique) : protège tous les chemins (register/unlock/hash/recover) et tous les bindings (WASM + futur FFI natif), plus seulement la couche WASM. - Énumération / récolte de clés : rate-limit dédié (20/min) sur
/api/users/lookup. - Machine à états d'adhésion :
POST /api/orgs/:id/acceptrefuse une adhésion noninvited(409).
- Lier
KdfParams+ email en AAD du chiffrement de l'USK (détecter une altération serveur des paramètres même au-dessus des planchers). Touche au format chiffré → migration à prévoir. - Zeroize des plaintexts déchiffrés et de la clé de récupération (Rust).
- Validation
EncStringà la désérialisation (longueur de nonce / ciphertext) ; AAD liantencrypted_key↔encrypted_datalors de la ré-enveloppe d'Org Key. - Rôles org : un
memberpeut créer des collections / octroyermanage; garde « dernier admin » absente — à arbitrer selon le modèle voulu. - Salt KDF déterministe (par email) : compromis assumé (pas d'aller-retour serveur) — à figer
en ADR.
cargo audit/osv-scanner+.strict()Zod en défense en profondeur.
- Pentest externe + programme de divulgation de vulnérabilités.
- Conformité nLPD/RGPD ; à terme SOC 2.
- Paramètres Argon2id à recalibrer selon le budget client (cible mémoire plus élevée).