Modèle de menaces & auto-attestation OWASP ASVS L1

Les menaces que Vaulted est conçu pour déjouer, celles qu'il ne déjoue pas, et une attestation contrôle par contrôle face à une référence du secteur.

Version 1.0 · Publié le 2026-04-27 · Source : main · Auteur : Maxim Novak

À propos de ce document

Il s'agit d'une auto-attestation, pas d'un audit tiers. Elle existe pour que tu puisses voir exactement ce que Vaulted prétend protéger, ce qu'il ne protège pas, et comment chaque décision de conception correspond à des contrôles reconnus. On commandera une revue indépendante et on publiera son rapport à côté de cette page dès que le budget le permettra. D'ici là, tu peux vérifier toi-même l'affirmation centrale zero-knowledge en cinq minutes avec les DevTools du navigateur.

1. Périmètre & hypothèses

Ce modèle couvre le déploiement en production de vaulted.fyi y compris son frontend web, ses routes d'API et son stockage Upstash Redis. Il couvre également le CLI et le serveur MCP publiés dans la mesure où ils interagissent avec la même API.

Hors périmètre :

  • L'appareil de l'utilisateur (navigateur, OS, extensions, presse-papiers, écran).
  • Le canal de communication par lequel le lien de partage est transmis (e-mail, Slack, SMS, etc.).
  • Le traitement ultérieur du texte en clair par le destinataire.
  • Les vulnérabilités de Vercel ou Upstash en dessous de la surface d'API que nous utilisons.

2. Actifs & frontières de confiance

Actif principal : le secret en clair. Il ne doit jamais atteindre le serveur, persister en dehors des navigateurs de l'expéditeur et du destinataire, ni être récupérable à partir du seul état côté serveur.

Actifs secondaires : le texte chiffré, les IV, les compteurs de consultations, les horodatages d'expiration, ainsi que l'intégrité et la disponibilité du service.

Frontières de confiance (par ordre de confiance décroissante) :

  1. Navigateur de l'expéditeur — de confiance avec le texte en clair et la clé.
  2. Navigateur du destinataire — de confiance avec le texte en clair et la clé après avoir saisi le lien.
  3. Réseau entre le client et le serveur — non fiable ; atténué par TLS 1.3 et le choix de conception selon lequel seul le texte chiffré le traverse.
  4. Serveur Vaulted (nous) — semi-fiable. Traité comme un stockage passif de texte chiffré. Le modèle de menaces suppose que Vaulted lui-même pourrait être compromis sans exposer le texte en clair.
  5. Upstash Redis — même niveau de confiance que le serveur. Uniquement des blobs chiffrés.

3. Acteurs de la menace

Observateur réseau passif. FAI, acteur sur le chemin ayant accès aux métadonnées TLS. Déjoué par TLS et par l'absence de texte en clair ou de clé sur le réseau.

Attaquant réseau actif. Peut tenter un MitM. Déjoué par TLS, le préchargement HSTS et la validation de certificat. Une compromission TLS réussie ne livre toujours que du texte chiffré.

Serveur compromis / opérateur hostile. Nous y compris. Ne peut pas lire les secrets stockés car la clé n'arrive jamais. Peut interrompre le service ou modifier le bundle JS servi — traité dans les risques résiduels ci-dessous.

Attaquant non authentifié disposant d'un lien de partage valide. Par conception, quiconque dispose du lien complet peut déchiffrer. Les limites de consultations, l'expiration et la phrase secrète optionnelle réduisent la fenêtre. C'est une propriété délibérée, pas un bug.

Attaquant ciblé contre un expéditeur ou un destinataire précis. Peut exploiter l'appareil, le canal de transmission ou le traitement du destinataire après déchiffrement. Hors du contrôle de Vaulted ; documenté par souci d'honnêteté.

4. Contrôles

  • AES-256-GCM côté client avec des IV aléatoires de 96 bits issus de crypto.getRandomValues.
  • Clés de 256 bits générées par secret via crypto.subtle.generateKey ; placées dans le fragment d'URL, jamais transmises.
  • Encapsulation optionnelle par phrase secrète avec PBKDF2 (nombre élevé d'itérations) et encapsulation de clé AES-GCM.
  • Application atomique du compteur de consultations via Redis HINCRBY avec suppression dans la même transaction à la limite.
  • Expiration automatique basée sur le TTL, plafonnée à 30 jours ; aucune prolongation après la création.
  • Limitation de débit par IP à fenêtre glissante sur les endpoints de création et de consultation.
  • noindex sur les pages de consultation /s/[id] afin que les URL de secrets ne puissent pas fuiter via la recherche.
  • TLS 1.3 avec préchargement HSTS, en-têtes de sécurité robustes, aucune journalisation d'IP au-delà des fenêtres de limitation de débit.

5. Risques résiduels (non couverts)

Ce sont des décisions de frontière délibérées, documentées pour que les utilisateurs puissent décider si Vaulted correspond à leur modèle de menaces.

  • Compromission de l'appareil. Un enregistreur de frappe, un navigateur infecté ou une extension hostile peut lire le texte en clair après déchiffrement.
  • Fuite par le canal de transmission. Si le lien de partage est transféré, archivé ou cité dans une réponse à un fil d'e-mails, ce canal devient la surface d'attaque.
  • Substitution ciblée du bundle. Un CDN ou un edge Vercel compromis pourrait servir un JS différent à un utilisateur précis. Subresource Integrity et les builds reproductibles sont des atténuations partielles et figurent sur la feuille de route.
  • Comportement du destinataire. Une fois déchiffré, le destinataire peut copier, capturer en image ou transférer.
  • Phrase secrète faible. Si elle est utilisée, une phrase secrète faible est cassable par force brute par quiconque dispose de la clé encapsulée.
  • Contrainte physique / coercition. Hors périmètre de tout contrôle technique.

6. Auto-attestation OWASP ASVS L1

La matrice ci-dessous met en correspondance l'implémentation de Vaulted avec une sélection d'exigences OWASP ASVS niveau 1. Les catégories non applicables (sessions, authentification, envoi de fichiers) sont marquées N/A avec une brève justification plutôt qu'omises, pour que l'absence d'une entrée ne soit pas perçue comme une esquive.

IDCatégorieExigenceStatutPreuve
V1.1.1ArchitectureSDLC sécurisé avec modélisation des menaces pour l'applicationPassCe document. Révisé à chaque changement d'architecture significatif.
V1.4.1ArchitectureDes points d'application de confiance appliquent les contrôles d'accèsPassLes gestionnaires de routes d'API valident les entrées et consomment les consultations de façon atomique via Redis HINCRBY dans src/lib/redis-secrets-store.ts.
V2.10.xAuthentificationAuthentification de service / d'utilisateurN/AVaulted est anonyme. Pas de comptes utilisateurs, pas d'authentification de service à service. L'autorisation repose sur la connaissance de l'identifiant du secret et de la clé du fragment d'URL.
V3.xGestion des sessionsExigences de gestion des sessionsN/APas de sessions, pas de cookies pour un état authentifié.
V5.1.3Validation des entréesValidation des entrées au niveau de la couche de service de confiancePassValidation manuelle à l'exécution dans src/app/api/secrets/route.ts. Charge utile ≤ 1000 caractères appliquée côté serveur ; nombre maximal de consultations et TTL bornés.
V5.2.5AssainissementEncodage de sortie selon le contexte (HTML, JS, URL)PassReact échappe par défaut toutes les valeurs interpolées. Les seuls appels dangerouslySetInnerHTML rendent des littéraux JSON-LD construits côté serveur à partir de données typées.
V6.2.1Cryptographie stockéeUtiliser des algorithmes cryptographiques approuvés avec des valeurs par défaut sûresPassAES-256-GCM via la Web Crypto API. NIST SP 800-38D. Voir src/lib/crypto.ts.
V6.2.2Cryptographie stockéeGénération de nombres aléatoires cryptographiquement fortsPasscrypto.getRandomValues pour les IV et le matériel de clé. crypto.subtle.generateKey pour les clés AES.
V6.2.5Cryptographie stockéeAucune primitive cryptographique non sécurisée ou obsolètePassAucun MD5, SHA-1, DES, RC4, ECB ou CBC-sans-MAC où que ce soit dans le chemin cryptographique.
V6.3.1Cryptographie stockéeClés protégées contre l'accès non autoriséPassLa clé de chiffrement n'atteint jamais le serveur. Elle ne vit que dans le fragment d'URL, traité côté client conformément au RFC 3986. Une phrase secrète optionnelle encapsule la clé avec PBKDF2 avant le partage.
V7.1.1Gestion des erreurs & journalisationAucune information sensible dans les journauxPassLe serveur journalise uniquement la forme de la requête et les décisions de limitation de débit. Aucun texte chiffré, aucun identifiant de secret d'une manière qui pourrait être recoupée, aucune IP persistée au-delà de la fenêtre de limitation de débit.
V7.4.1Gestion des erreurs & journalisationMessages d'erreur génériquesPassLes routes d'API renvoient des codes de statut HTTP génériques et de courtes chaînes d'erreur. Aucune trace de pile ni état interne divulgué.
V8.1.1Protection des donnéesDonnées sensibles identifiées et protégéesPassLe texte en clair n'est jamais reçu par le serveur. Le texte chiffré est stocké chiffré au repos dans Upstash Redis avec suppression basée sur le TTL et application atomique de la limite de consultations.
V8.3.1Protection des donnéesDonnées sensibles non exposées dans les URL ou les référentsPassLa clé de chiffrement vit dans le fragment d'URL ; les fragments ne sont jamais envoyés au serveur et sont retirés de document.referrer par les navigateurs conformément au RFC 3986 §3.5.
V9.1.1CommunicationsTLS pour toute la connectivité clientPassTLS 1.3 appliqué à l'edge Vercel. HSTS préchargé. Les requêtes HTTP sont redirigées vers HTTPS.
V10.3.2Code malveillantCode applicatif examiné pour détecter du code malveillantPassBase de code à mainteneur unique. Tous les commits sont rédigés par le propriétaire du projet ; commits signés là où c'est pris en charge. Les mises à jour de dépendances via Dependabot sont examinées avant le merge.
V11.1.1Logique métierFlux logiques protégés contre les abusPassLimitation de débit par IP via Upstash Ratelimit (10 créations/min, 30 consultations/min). Compteurs de consultations décrémentés de façon atomique.
V12.xFichiers & ressourcesExigences d'envoi et de traitement de fichiersN/AVaulted n'accepte aucun envoi de fichiers.
V13.2.1API & services webLes endpoints RESTful valident le schéma de requêtePassTous les gestionnaires POST/GET valident les paramètres de chemin, la forme du corps et le content-type avant traitement.
V14.4.3ConfigurationEn-têtes de sécurité standard configurésPassHSTS, X-Content-Type-Options, Referrer-Policy et Permissions-Policy définis via la configuration Next.js. Content-Security-Policy appliquée par requête dans src/proxy.ts avec un script-src strict-dynamic basé sur un nonce ; les routes d'API reçoivent une politique verrouillée default-src none.

La numérotation suit la structure ASVS 4.0. La liste est sélective, pas exhaustive — l'objectif est d'être honnête sur les contrôles qui s'appliquent réellement à un stockage de texte chiffré sans état et sans compte.

7. Processus de changement

Tout changement qui affecte un élément de ce document — nouvel endpoint, changement cryptographique, refactoring touchant les dépendances, changement d'infrastructure — doit déclencher une révision de cette page dans la même PR. La version et la date de publication ci-dessus sont incrémentées lorsque le document est mis à jour ; la version précédente reste accessible dans l'historique git public.

Validation

Ce modèle de menaces est publié de bonne foi par le mainteneur de Vaulted. Les erreurs, omissions et désaccords avec les attestations ci-dessus sont explicitement les bienvenus — merci de les signaler à [email protected] ou via le programme de divulgation responsable.

Maxim Novak — mainteneur, vaulted.fyi · 2026-04-27