Modelo de amenazas y autoatestación OWASP ASVS L1

Las amenazas que Vaulted está diseñado para vencer, las que no, y una atestación control por control frente a una base de referencia del sector.

Versión 1.0 · Publicado el 2026-04-27 · Origen: main · Autor: Maxim Novak

Acerca de este documento

Esto es una autoatestación, no una auditoría de terceros. Existe para que puedas ver exactamente qué afirma proteger Vaulted, qué no, y cómo cada decisión de diseño se corresponde con controles reconocidos. Encargaremos una revisión independiente y publicaremos su informe junto a esta página cuando el presupuesto lo permita. Hasta entonces, puedes verificar tú mismo la afirmación central de conocimiento cero en cinco minutos con las DevTools del navegador.

1. Alcance y supuestos

Este modelo cubre el despliegue de producción de vaulted.fyi incluyendo su frontend web, sus rutas de API y el almacenamiento en Upstash Redis. También cubre el CLI publicado y el servidor MCP en la medida en que interactúan con la misma API.

Fuera del alcance:

  • El dispositivo del usuario (navegador, sistema operativo, extensiones, portapapeles, pantalla).
  • El canal de comunicación por el que se entrega el enlace compartido (correo, Slack, SMS, etc.).
  • El manejo posterior del texto plano por parte del destinatario.
  • Vulnerabilidades en Vercel o Upstash por debajo de la superficie de API que consumimos.

2. Activos y fronteras de confianza

Activo principal: el secreto en texto plano. Nunca debe llegar al servidor, persistir fuera de los navegadores del remitente y del destinatario, ni ser recuperable solo a partir del estado del lado del servidor.

Activos secundarios: el texto cifrado, los IV, los contadores de vistas, las marcas de tiempo de expiración y la integridad / disponibilidad del servicio.

Fronteras de confianza (en orden decreciente de confianza):

  1. Navegador del remitente — de confianza con el texto plano y la clave.
  2. Navegador del destinatario — de confianza con el texto plano y la clave tras introducir el enlace.
  3. Red entre el cliente y el servidor — no confiable; mitigado por TLS 1.3 y por la decisión de diseño de que solo el texto cifrado la atraviesa.
  4. Servidor de Vaulted (nosotros) — de confianza parcial. Tratado como un almacén pasivo de texto cifrado. El modelo de amenazas asume que el propio Vaulted podría verse comprometido sin exponer el texto plano.
  5. Upstash Redis — mismo nivel de confianza que el servidor. Solo bloques cifrados.

3. Actores de amenaza

Observador pasivo de la red. ISP, actor en la ruta con acceso a metadatos de TLS. Vencido por TLS y por la ausencia de texto plano o clave en el cable.

Atacante activo de la red. Puede intentar un MitM. Vencido por TLS, la precarga de HSTS y la validación de certificados. Un compromiso exitoso de TLS sigue revelando solo texto cifrado.

Servidor comprometido / operador hostil. Nos incluye a nosotros. No puede leer los secretos almacenados porque la clave nunca llega. Puede denegar el servicio o modificar el bundle de JS servido, lo que se aborda en los riesgos residuales más abajo.

Atacante no autenticado con un enlace compartido válido. Por diseño, cualquiera con el enlace completo puede descifrar. Los límites de vistas, la expiración y la frase de contraseña opcional reducen la ventana. Es una propiedad deliberada, no un fallo.

Atacante dirigido contra un remitente o destinatario concreto. Puede explotar el dispositivo, el canal de entrega o el manejo del texto plano por parte del destinatario tras el descifrado. Fuera del control de Vaulted; documentado por honestidad.

4. Controles

  • AES-256-GCM del lado del cliente con IV aleatorios de 96 bits de crypto.getRandomValues.
  • Claves de 256 bits generadas por secreto mediante crypto.subtle.generateKey; colocadas en el fragmento de la URL, nunca transmitidas.
  • Envoltorio opcional con frase de contraseña usando PBKDF2 (recuento de iteraciones alto) y envoltura de clave AES-GCM.
  • Aplicación atómica del recuento de vistas mediante el HINCRBY de Redis con eliminación en la misma transacción al alcanzar el límite.
  • Expiración automática basada en TTL limitada a 30 días; sin prórroga tras la creación.
  • Límite de tasa por IP con ventana deslizante en los endpoints de creación y visualización.
  • noindex en las páginas de visualización /s/[id] para que las URL de los secretos no puedan filtrarse a través de las búsquedas.
  • TLS 1.3 con precarga de HSTS, cabeceras de seguridad robustas, sin registro de IP más allá de las ventanas de límite de tasa.

5. Riesgos residuales (no defendidos)

Son decisiones de frontera deliberadas, documentadas para que los usuarios puedan decidir si Vaulted encaja en su modelo de amenazas.

  • Compromiso del dispositivo. Un keylogger, un navegador infectado o una extensión hostil pueden leer el texto plano tras el descifrado.
  • Filtración del canal de entrega. Si el enlace compartido se reenvía, se archiva o se cita en un hilo de correo respondido, ese canal se convierte en la superficie de ataque.
  • Sustitución dirigida del bundle. Una CDN o un edge de Vercel comprometidos podrían servir un JS distinto a un usuario concreto. La Subresource Integrity y las compilaciones reproducibles son mitigaciones parciales y están en la hoja de ruta.
  • Comportamiento del destinatario. Una vez descifrado, el destinatario puede copiarlo, capturarlo o reenviarlo.
  • Frase de contraseña débil. Si se usa, una frase de contraseña débil es vulnerable a fuerza bruta por cualquiera que tenga la clave envuelta.
  • Coacción / tortura. Fuera del alcance de cualquier control técnico.

6. Autoatestación OWASP ASVS L1

La matriz siguiente asigna la implementación de Vaulted a una selección de requisitos de OWASP ASVS nivel 1. Las categorías que no aplican (sesiones, autenticación, carga de archivos) se marcan como N/A con una breve justificación en lugar de omitirse, para que la ausencia de una entrada no se interprete como evasión.

IDCategoríaRequisitoEstadoEvidencia
V1.1.1ArquitecturaSDLC seguro con modelado de amenazas para la aplicaciónPassEste documento. Revisado en cada cambio material de la arquitectura.
V1.4.1ArquitecturaLos puntos de aplicación de confianza imponen los controles de accesoPassLos manejadores de rutas de la API validan las entradas y consumen vistas de forma atómica mediante Redis HINCRBY en src/lib/redis-secrets-store.ts.
V2.10.xAutenticaciónAutenticación de servicio / usuarioN/AVaulted es anónimo. Sin cuentas de usuario, sin autenticación de servicio a servicio. La autorización se basa en el conocimiento del ID del secreto y de la clave del fragmento de la URL.
V3.xGestión de sesionesRequisitos de gestión de sesionesN/ASin sesiones, sin cookies para estado autenticado.
V5.1.3Validación de entradasValidación de entradas en la capa de servicio de confianzaPassValidación manual en tiempo de ejecución en src/app/api/secrets/route.ts. Payload ≤ 1000 caracteres aplicado en el servidor; máximo de vistas y TTL acotados.
V5.2.5SaneamientoCodificación de salida según el contexto (HTML, JS, URL)PassReact escapa por defecto todos los valores interpolados. Las únicas llamadas a dangerouslySetInnerHTML renderizan literales JSON-LD construidos en el servidor a partir de datos tipados.
V6.2.1Criptografía almacenadaUsar algoritmos criptográficos aprobados con valores predeterminados segurosPassAES-256-GCM mediante la Web Crypto API. NIST SP 800-38D. Véase src/lib/crypto.ts.
V6.2.2Criptografía almacenadaGeneración de números aleatorios criptográficamente fuertePasscrypto.getRandomValues para los IV y el material de clave. crypto.subtle.generateKey para las claves AES.
V6.2.5Criptografía almacenadaSin primitivas criptográficas inseguras u obsoletasPassSin MD5, SHA-1, DES, RC4, ECB ni CBC sin MAC en ninguna parte de la ruta criptográfica.
V6.3.1Criptografía almacenadaClaves protegidas frente al acceso no autorizadoPassLa clave de cifrado nunca llega al servidor. Vive solo en el fragmento de la URL, procesada en el cliente según el RFC 3986. Una frase de contraseña opcional envuelve la clave con PBKDF2 antes de compartirla.
V7.1.1Manejo de errores y registroSin información sensible en los registrosPassEl servidor solo registra la forma de la solicitud y las decisiones del límite de tasa. Sin texto cifrado, sin IDs de secreto de forma que puedan correlacionarse, sin IP persistidas más allá de la ventana del límite de tasa.
V7.4.1Manejo de errores y registroMensajes de error genéricosPassLas rutas de la API devuelven códigos de estado HTTP genéricos y cadenas de error breves. No se filtran trazas de pila ni estado interno.
V8.1.1Protección de datosDatos sensibles identificados y protegidosPassEl servidor nunca recibe el texto plano. El texto cifrado se almacena cifrado en reposo en Upstash Redis, con eliminación basada en TTL y aplicación atómica del límite de vistas.
V8.3.1Protección de datosDatos sensibles no expuestos en URLs ni referrersPassLa clave de cifrado vive en el fragmento de la URL; los fragmentos nunca se envían al servidor y los navegadores los eliminan de document.referrer según el RFC 3986 §3.5.
V9.1.1ComunicacionesTLS para toda la conectividad del clientePassTLS 1.3 aplicado en el edge de Vercel. HSTS precargado. Las solicitudes HTTP se redirigen a HTTPS.
V10.3.2Código maliciosoCódigo de la aplicación revisado en busca de código maliciosoPassBase de código de un único mantenedor. Todos los commits son del propietario del proyecto; commits firmados cuando es posible. Las actualizaciones de dependencias mediante Dependabot se revisan antes de fusionarlas.
V11.1.1Lógica de negocioFlujos de lógica protegidos frente al abusoPassLímite de tasa por IP mediante Upstash Ratelimit (10 creaciones/min, 30 vistas/min). Los contadores de vistas se decrementan de forma atómica.
V12.xArchivos y recursosRequisitos de carga y procesamiento de archivosN/AVaulted no acepta cargas de archivos.
V13.2.1API y servicios webLos endpoints RESTful validan el esquema de la solicitudPassTodos los manejadores POST/GET validan los parámetros de ruta, la forma del cuerpo y el content-type antes de procesar.
V14.4.3ConfiguraciónCabeceras de seguridad estándar configuradasPassHSTS, X-Content-Type-Options, Referrer-Policy y Permissions-Policy establecidas mediante la configuración de Next.js. Content-Security-Policy aplicada por solicitud en src/proxy.ts con un script-src strict-dynamic basado en nonce; las rutas de la API reciben una política restrictiva default-src none.

La numeración sigue la estructura de ASVS 4.0. La lista es seleccionada, no exhaustiva: el objetivo es ser honestos sobre los controles que aplican de forma significativa a un almacén de texto cifrado sin estado y sin cuentas.

7. Proceso de cambios

Cualquier cambio que afecte a un elemento de este documento — nuevo endpoint, cambio criptográfico, refactorización que afecte a dependencias, cambio de infraestructura — debe desencadenar una revisión de esta página en el mismo PR. La versión y la fecha de publicación de arriba se incrementarán cuando se actualice el documento; la versión anterior permanece accesible en el historial público de git.

Firma

Este modelo de amenazas se publica de buena fe por parte del mantenedor de Vaulted. Se invitan explícitamente errores, omisiones y desacuerdos con las atestaciones anteriores: por favor, comunícalos a [email protected] o a través del programa de divulgación responsable.

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