Seguridad en qub
Fecha de entrada en vigor: 23 de septiembre de 2026 Versión: 1.1 — revisión de precisión de la implementación
Para investigadores — referencia rápida:
- Dónde enviar reportes: support@qub.social con el prefijo de asunto
[SECURITY].- Qué incluir: la vulnerabilidad, los pasos para reproducirla y cualquier prueba de concepto.
- Nuestra respuesta: acusamos recibo dentro de los 3 días hábiles y buscamos enviar una corrección dentro de los 90 días.
- Safe Harbor: no emprenderemos acciones legales contra investigaciones de buena fe que sigan las reglas en §12 (sin acceder a datos que no son tuyos, sin degradar el servicio, sin retener los datos obtenidos más allá de lo necesario para demostrar el problema, dándonos una ventana razonable de divulgación).
Los detalles completos están en §12 (Divulgación coordinada).
Quiénes somos
qub.social es operado por VSPRY AUSTRALIA PTY LIMITED (ABN 41 631 026 330), Level 38, 71 Eagle Street, Brisbane QLD 4000, Australia. Las referencias a "qub", "nosotros", "nos" y "nuestro" se refieren a esa entidad.
Contacto de seguridad: support@qub.social con el prefijo de asunto [SECURITY].
1. Nuestro enfoque
qub es infraestructura de confianza. El producto no vale nada si no es seguro, así que la seguridad no es una característica — es el sustrato. Esta página describe, en términos concretos, cómo protegemos nuestro stack, tus datos y la integridad del contenido sellado.
El valor de un compromiso temporal verificable crece a medida que una parte mayor de internet es generada por máquinas. Una transacción de almacenamiento verificada o un anclaje del registro de transparencia puede establecer que un texto cifrado existía a más tardar en la hora de su bloque; el artefacto sellado demuestra por separado la integridad del contenido, la vinculación con la ronda de drand y cualquier firma de autoría. Mantener separadas estas afirmaciones es la vara con la que se mide esta página.
No te pedimos que confíes en nosotros. Diseñamos para que la confianza requerida en nosotros sea lo más pequeña posible, y donde se requiere confianza explicamos exactamente qué se está confiando y por qué.
Tres principios guían cada decisión de diseño:
- Minimizar lo que el servidor puede ver. En el flujo de mensajes predeterminado del navegador, el texto plano y la clave de la envoltura permanecen en tu dispositivo. El sellado Builder del lado del servidor, la cofirma de pactos y la recuperación habilitada de forma explícita tienen otros límites de confianza, descritos más abajo. Cuando conservamos metadatos, los limitamos a lo que necesita la función elegida.
- Hacer que el compromiso esté localmente contenido. Una brecha en cualquier componente (nuestro servidor, el proveedor de correo, un nodo de drand) no debería revelar contenido sellado que aún no haya alcanzado su hora de revelación.
- Hacer el protocolo auditable. El artefacto sellado es verificable de extremo a extremo con criptografía pública. No necesitas confiar en qub el servicio para verificar un qub el artefacto.
2. Modelo de amenazas
2.1 Contra qué protegemos
- Un atacante que obtiene acceso de lectura a nuestros datos almacenados del lado del servidor antes de la hora de revelación. En el flujo privado predeterminado del navegador obtiene metadatos y bytes envueltos opacos, no texto plano ni K. Esta protección no se aplica a una K conservada de forma explícita para recuperación, a una entrega pública sin envoltura después de su ronda de drand ni al texto plano suministrado transitoriamente a
/api/v1/sealde Builder y a los flujos de pactos. - Un atacante que intercepta el tráfico entre tu navegador y nuestra infraestructura. TLS termina en el borde de nuestro CDN; las cargas útiles selladas ya están cifradas antes del tránsito.
- Un atacante que manipula una carga útil almacenada. La autenticación de la envoltura externa (cuando existe), la decodificación canónica, el hash del cuerpo, la nueva derivación de
qub_id, la vinculación con la ronda y las firmas opcionales hacen que la manipulación no supere la verificación; el lector se niega a renderizarla. - Un atacante que intenta vincular un correo de autor falsificado a una clave de firma. La attestation por correo electrónico requiere la posesión tanto de la clave privada de firma como de un código de un solo uso entregado a la bandeja del correo.
- Un operador de baliza drand comprometido. La red drand usa firmas BLS de umbral entre múltiples operadores independientes; una minoría no puede falsificar firmas de liberación temprana.
2.2 Contra qué no podemos proteger
Somos honestos sobre nuestros límites. qub no puede defender contra:
- Un compromiso de tu dispositivo antes de que selles. Keyloggers locales, extensiones de navegador maliciosas o el acceso físico a un dispositivo desbloqueado pueden capturar el texto plano en el punto de redacción.
- Un colapso del umbral de drand. Múltiples organizaciones independientes ejecutan la red drand específicamente para hacer esto difícil, pero no es criptográficamente imposible: si suficientes operadores conspiran, podrían derivar las claves timelock antes.
- Las propiedades de revelación de una copia válida. Un qub público sin envoltura pasa a ser descifrable después de su ronda de drand. Un qub privado envuelto requiere además K; quien obtenga tanto los bytes almacenados como K podrá descifrarlo después de la ronda. Los registros del almacenamiento permanente y del registro anclado no pueden retirarse simplemente eliminándolos de la superficie del producto de qub.
- Un adversario global que rompa la criptografía subyacente (AES-GCM, las suposiciones de emparejamiento de BLS12-381, SHA3-256, ML-DSA-65). Si estos primitivos caen, el ecosistema criptográfico en general tiene problemas mayores.
3. Criptografía del lado del cliente
En el flujo de mensajes predeterminado del navegador, el contenido se cifra antes de la solicitud de subida. Hay dos rutas explícitas distintas: /api/v1/seal de Builder envía deliberadamente el texto plano y una K generada por quien llama al Worker para sellarlos en memoria, y la preparación y cofirma de pactos envía el pacto estructurado y firmado al servicio para que este finalice el artefacto bilateral. Ninguna de estas excepciones debe confundirse con el cifrado de extremo a extremo de la ruta del navegador.
3.1 Cifrado timelock
qub usa tlock — cifrado basado en identidad, indexado a una ronda futura de la baliza drand. El cifrado se realiza en tu navegador usando la clave pública de la red drand; la clave de descifrado es liberada públicamente por la red drand solo cuando se alcanza la ronda objetivo. Nadie, incluidos nosotros, puede reconstruir la clave de descifrado por adelantado.
Apuntamos a la cadena quicknet:
- período de ronda de 3 segundos
- Modo desencadenado (cada ronda es independiente)
- Firmas BLS12-381 G1
- Hash de cadena
52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971
La clave pública de la cadena quicknet y el genesis time están compilados en el cliente. No obtenemos los parámetros de la cadena en tiempo de ejecución, así que un nodo malicioso no puede sustituir una cadena que controlemos.
3.2 Cifrado simétrico
El esquema tlock envuelve una clave de contenido AES-256-GCM. AES-GCM provee cifrado autenticado: un solo bit volteado en el ciphertext causa que el descifrado falle, en vez de producir texto plano corrompido silenciosamente.
3.3 Serialización canónica
Las estructuras del protocolo se serializan mediante CBOR determinista (RFC 8949 §4.2, codificación determinista básica). Dos implementaciones que codifican la misma estructura lógica producen CBOR idéntico. Las cargas útiles selladas completas no son deterministas: tlock y el cifrado de la envoltura externa usan aleatoriedad nueva. El hash del cuerpo se calcula sobre los bytes sin procesar del cuerpo, mientras que la codificación canónica hace inequívocas las estructuras firmadas y de transmisión que lo rodean.
Escribimos el codificador CBOR a mano tanto para nuestra implementación cliente como para la del servidor en lugar de depender de una biblioteca de serialización genérica — el requerimiento es exactitud, no ergonomía, y se ejecutan tests de propiedad en ambas implementaciones para verificar que coinciden.
Un test de regresión afirma que el formato canónico de transmisión no contiene ninguna secuencia de bytes con la marca qub más allá de la clave de campo qub_id, primitiva del protocolo. El formato de transmisión es intencionalmente agnóstico de marca — cualquier lector conforme (el nuestro o el de un tercero) puede renderizar cualquier qub desde el almacenamiento permanente, independientemente de qué despliegue lo selló. El test es un trampolín que evita que un cambio futuro hornee accidentalmente una referencia de marca en bytes que, una vez en el almacenamiento permanente, no pueden reescribirse.
3.4 Hashing del cuerpo e integridad pre-revelación
Cada carga útil sellada lleva un hash SHA3-256 de los bytes sin procesar de su cuerpo. El hash está vinculado a qub_id y, cuando se habilita la firma de autoría, a la entrada de firma V2. Un lector lo vuelve a calcular después del descifrado y rechaza cualquier discrepancia.
El identificador de contenido de 32 bytes qub_id se deriva de una preimagen de 108 bytes que abarca la versión del protocolo, el tipo de contenido, las marcas de tiempo de creación y desbloqueo, la marca temporal opcional del resultado (o su centinela cero), la ronda de drand objetivo, el hash del cuerpo y el SHA3-256 del título opcional normalizado en NFC. Un gateway o CDN no puede modificar de forma coherente ningún campo vinculado y superar la nueva derivación. Los títulos están limitados a 100 puntos de código NFC y se rechaza en ellos la clase compartida de puntos de código hostiles o de control (incluidos los controles bidireccionales, los caracteres de ancho cero, el bloque de etiquetas, BOM, C0, C1 y DEL).
3.5 Firma (ML-DSA-65)
La firma de autoría usa ML-DSA-65 (FIPS 204), un esquema de firma post-cuántico estandarizado por NIST. Elegimos deliberadamente un primitivo post-cuántico para la firma porque el contenido sellado es permanente: una firma que verifica hoy debe seguir verificando dentro de décadas, incluso después de que las computadoras cuánticas a gran escala se vuelvan prácticas.
Las claves de firma se generan en el navegador. El secreto local se envuelve bajo una clave WebCrypto no extraíble antes de almacenarse en IndexedDB. Si se usa la función de recuperación multidispositivo vinculada a la cuenta, se almacena en el servidor un blob portátil de clave cifrado con AEAD; el texto cifrado de su clave secreta queda vinculado al identificador inmutable de la cuenta, y el servicio valida la envoltura pública pero no puede descifrar el material secreto. Los bytes sin procesar de la clave privada no se envían al servidor. Las claves públicas y los registros de atestación se almacenan para la verificación y la presentación de la identidad.
El mismo descifrado tlock en el navegador se aplica dentro de la incrustación de qub: cuando un qub sellado se renderiza a través de <qub-embed> en una página de terceros, el descifrado igual sucede en el iframe de incrustación dentro del navegador del lector. La incrustación no cambia el modelo de confianza — el texto plano nunca se descifra en un servidor de qub.
3.6 Atribución pública — Opcional
Los qubs sellados no llevan ningún puntero on-chain a su creador a menos que el creador elija explícitamente adjuntar uno. Cuando sellas un qub, la app de referencia emite una etiqueta Author de almacenamiento (un fingerprint hexadecimal de 64 caracteres de tu clave pública de firma) solo cuando "Atribución pública" está activada en el paso del selector de fecha. Con el toggle desactivado — el predeterminado — no se escribe ninguna etiqueta Author y el qub queda sin atribución en el almacenamiento permanente: nada en el almacenamiento vincula la subida con tu handle, tu correo electrónico o tus otros qubs. Con el toggle activado, el fingerprint se resuelve a tu @handle a través de la cadena de attestation en §6.3 / §10 y la cuenta regresiva del lector muestra "Sellado por @{handle}" antes de la revelación.
Esto es una protección deliberada contra el riesgo de enumeración que crearía una etiqueta Author siempre activada: un tercero que descubra el fingerprint de un creador podría, de otro modo, hacer grep en el almacenamiento permanente por la etiqueta y reconstruir la totalidad del output histórico de ese creador. La atribución opcional cierra ese canal — solo los qubs que el creador elige explícitamente atribuir aparecen bajo un fingerprint en el almacenamiento permanente.
La página de perfil /u/{handle} es una tarjeta de identidad verificada — handle, nombre para mostrar y URL opcionales, badge "correo verificado" (sin la dirección), y la forma corta del fingerprint criptográfico. No lista los qubs de un creador. Los visitantes que quieran ver un qub específico de un creador siguen la URL de entrega de ese qub directamente.
3.7 Envoltura externa de cifrado
Incluso después de que el descifrado timelock sea matemáticamente posible —una vez publicada la firma de drand de la ronda vinculada—, la capa timelock canónica por sí sola permitiría a un indexador descifrar en masa los qubs que pueda encontrar. La entrega privada cierra ese canal con una capa simétrica adicional alrededor de los bytes cifrados con timelock (Protocolo §13). La entrega pública omite deliberadamente la envoltura para que los enlaces de notificación, incrustación y descubrimiento funcionen sin un fragmento secreto.
La envoltura usa AES-256-GCM, un cifrado autenticado estandarizado por NIST, con una clave fresca de 256 bits K generada por qub por el CSPRNG de tu navegador. K está vinculada al qub_id del qub como datos adicionales autenticados, así que una clave de un qub no puede reutilizarse para descifrar un qub diferente.
K nunca llega a nuestros servidores en el flujo privado predeterminado del navegador. Está codificada en el fragmento de URL del enlace para compartir (https://qub.social/c/<tx_id>#<base64url(K)>). Los navegadores no transmiten los fragmentos de URL a los servidores —RFC 3986 coloca el fragmento fuera de la solicitud—, así que qub.social, los gateways de almacenamiento, los CDN y el monitoreo de solicitudes no ven K en ese flujo. El OuterWrapper almacenado es CBOR estructurado reconocible, pero su campo de texto cifrado autenticado oculta la estructura interna de SealedQub y no puede abrirse sin K.
Consecuencias netas:
- qub.social no puede descifrar los sellados privados predeterminados del navegador solo a partir de los datos almacenados. Un compromiso del almacén alcanza texto cifrado opaco sin K. Los qubs públicos y los que tienen recuperación habilitada presentan una exposición distinta por diseño.
- La pérdida del fragmento es irrecuperable sin un canal de recuperación elegido. Si guardas un enlace privado sin el fragmento y no habilitaste la recuperación, el qub queda ilegible a través de ese enlace. Por eso, el flujo de sellado muestra una advertencia explícita para guardar la URL.
- Recuperación opcional. Cuando aceptas correos del ciclo de vida del creador para un qub Y el correo coincide con tu identidad verificada, aceptamos K con la subida, almacenamos la URL completa de entrega en el registro sealed-history de tu identidad, y la usamos como el enlace en el correo de confirmación de sellado. Este intercambio — un canal de recuperación del lado del servidor a cambio de algo de pureza extremo a extremo — se activa solo con consentimiento explícito y solo para ese qub. La postura por defecto es crypto-shredding.
El endpoint del lado del servidor /api/v1/seal del Worker (usado por agentes de IA y otros llamantes de la API) requiere que el llamante genere K con un CSPRNG, la conserve localmente y la suministre como wrapper_key_b64url. El Worker necesariamente ve tanto el texto plano como K en memoria en esta ruta explícitamente confiable, pero no persiste ninguno de los dos. Un Idempotency-Key obligatorio evita que una respuesta perdida cree un segundo qub facturado, mientras que la K conservada por el llamante puede combinarse con la URL sin fragmento reproducida. Esto difiere de la ruta de navegador por defecto, donde K nunca llega al Worker a menos que el creador habilite explícitamente la recuperación.
4. Transporte y borde
4.1 TLS
El tráfico del navegador a qub se sirve por HTTPS en el borde de Cloudflare. Las respuestas establecen HTTP Strict Transport Security (max-age=63072000; includeSubDomains; preload). La versión exacta de TLS y el conjunto de cifrado negociados se rigen por la configuración activa del borde, no por afirmaciones del código de la aplicación. No exponemos un servidor de origen alcanzable por separado.
4.2 Seguridad del contenido
El cliente compilado se sirve con encabezados estrictos de tipo de contenido y de caché. La shell SPA es de un solo origen. No incrustamos scripts de terceros para analítica o publicidad. Los dos puntos de contacto con terceros en el producto están ambos limitados de forma estrecha: el flujo de compra deja la SPA por completo con una redirección de página completa al checkout alojado por Stripe (https://checkout.stripe.com/…) — la UI de Stripe nunca se ejecuta en nuestro origen y nunca vemos los datos de la tarjeta — y el flujo de sellado carga el widget Turnstile de Cloudflare, una alternativa de CAPTCHA respetuosa con la privacidad que Cloudflare renderiza dentro de su propio iframe sandboxed. Ninguna de las partes puede leer el resto de la página.
El iframe de incrustación de qub (servido desde qub.social/embed/{tx_id} y cargado en sitios de terceros por embed.js) lleva su propia Content-Security-Policy. Su lista permitida de connect-src es 'self', https://qub.social, https://arweave.net, https://ar-io.dev, https://permagate.io, https://api.drand.sh y https://drand.cloudflare.com. El iframe se ejecuta con sandbox="allow-scripts allow-top-navigation-by-user-activation" (sin allow-same-origin): la página anfitriona no puede leer su DOM, y el iframe no puede navegar la página anfitriona salvo tras una acción del usuario.
4.3 CORS y alcance de fetch
El cliente del navegador hace solicitudes fetch solo a:
- Nuestra propia API (
api.qub.socialy los equivalentes de staging) - Gateways de almacenamiento (solo lectura, para obtener bytes privados envueltos o públicos sin envoltura — §3.6)
- Endpoints de baliza drand (solo lectura, para las firmas de ronda en el momento de revelación)
Los destinos de la incrustación se aplican mediante su CSP. Los destinos previstos de la SPA principal están fijados en el código y la configuración y se ejercitan mediante comprobaciones de navegador e integración; Subresource Integrity no es un control de destinos de red.
La incrustación obtiene los bytes almacenados a través de los orígenes de qub o almacenamiento permitidos, desenvuelve las cargas útiles privadas en el navegador usando K del fragmento de su URL y obtiene de los dos orígenes de drand permitidos las firmas de la ronda en el momento de revelación. La SPA principal usa el conjunto alternativo de cuatro endpoints de config/drand-endpoints.json (drand.cloudflare.com, api.drand.sh, api2.drand.sh y api3.drand.sh) para que la caída de uno no impida la revelación. La CSP de la incrustación deniega las conexiones ajenas a su lista explícita.
5. Infraestructura del lado del servidor
5.1 Borde serverless
Nuestra API se ejecuta enteramente en un runtime serverless gestionado en el borde. No hay VMs, ni contenedores, ni procesos de servidor persistentes que administremos. Esto reduce drásticamente la superficie de ataque de la que somos responsables: no ejecutamos un sistema operativo, un servidor web ni un runtime de aplicación que debamos parchear.
Se aplica un middleware público-CORS separado Access-Control-Allow-Origin: * al siguiente conjunto de ruta implementada: /embed.js, /embed/v1.js, todo debajo /embed/; /api/v1/telemetry; /api/v1/openapi.json; todo debajo /api/v1/qub/ (incluyendo bytes, metadatos, prueba, participación, notificación y subrutas push); todo debajo de /api/v1/log/; búsquedas de manejadores públicos bajo /api/v1/handle/; y el avatar público lee debajo /api/v1/identity/avatar/. Sus permisos de prevuelo GET, POST, y OPTIONS con el Content-Type encabezado de solicitud. Esta superficie basada en prefijos es más amplia que solo las llamadas que actualmente realiza el embed, por lo que cada manejador por debajo de esos prefijos debe seguir aplicando su propia validación, autenticación, límites de tasa y controles de abuso. Otros caminos de la API mantienen la política CORS restringida de qub.social.
5.2 Almacenamiento
- Los almacenes de metadatos y coordinación conservan registros de identidad y atestación, derechos y referencias de facturación, registros de claves API, entradas de la lista de bloqueo, sesiones, estado de idempotencia, colas y estado de límites de tasa y concurrencia. Las distintas necesidades de coherencia usan KV, D1 y Durable Objects en vez de un único almacén universal.
- Nuestro almacén de objetos también es un sustrato de durabilidad. Conserva exactamente los bytes envueltos o sin envoltura de los qubs confirmados al subirlos, las hojas del registro de transparencia y los nodos de Merkle indexados por coordenadas, el material de anclaje, registros de eventos estructurados y cachés de respuestas y metadatos.
- El almacenamiento público permanente conserva los anclajes del registro de transparencia y, para la ruta T3 o una publicación diferida, las transacciones individuales de qubs. No operamos esa red. Las cargas útiles privadas del navegador permanecen opacas allí salvo que quien las tenga posea también K; las cargas públicas sin envoltura no tienen deliberadamente esa capa adicional de capacidad mediante enlace.
El flujo de mensajes predeterminado del navegador no conserva texto plano en la infraestructura de qub. /api/v1/seal de Builder procesa el texto plano y K en memoria, pero no conserva ninguno. La preparación de pactos necesariamente almacena el pacto estructurado y firmado hasta que se cofirma, se retira o caduca. La recuperación opcional almacena una capacidad de entrega (el enlace completo con fragmento) para recuperarla más tarde. Por tanto, no describimos todo el nivel de almacenamiento como «solo metadatos».
5.3 Secretos
Los secretos (billeteras de firma, tokens de proveedores y claves HMAC) se suministran mediante vinculaciones de secretos o entorno de la plataforma, no mediante el control de versiones. Los componentes en ejecución reciben solo las vinculaciones que necesitan. Los procedimientos de rotación y solapamiento son específicos de cada componente; no afirmamos que exista un único mecanismo universal de rotación automática o auditada.
5.4 Logging y telemetría
Se escriben logs JSON estructurados en cada solicitud de API con un correlation ID expuesto en el encabezado de respuesta X-Request-Id. La telemetría del cliente es anónima — sin identificador de dispositivo, sin dirección IP, sin vista previa del contenido. Los eventos se almacenan en memoria y se envían en base a mejor esfuerzo; un envío fallido se descarta, no se reintenta. La telemetría está diseñada para ser desactivable a nivel de red sin afectar al producto.
6. Autenticación
6.1 Inicio de sesión por magic-link
El inicio de sesión usa un token de un solo uso firmado con HMAC y enviado a tu bandeja de correo. El enlace es válido durante 15 minutos y su canje se reclama de forma atómica, por lo que los usos simultáneos o repetidos fallan de forma segura. Si tiene éxito, el navegador recibe una cookie opaca __Host-qub_session con los atributos Secure, HttpOnly, SameSite=Strict y Path=/.
Las sesiones tienen un límite de inactividad de 30 días y un límite absoluto de 90 días, rotan después de 24 horas y solo aceptan la generación inmediatamente anterior durante un período de gracia de 120 segundos por pérdida de respuesta. Las modificaciones sensibles de la cuenta requieren haberse autenticado en los 10 minutos anteriores. El secreto de firma HMAC es una vinculación de la plataforma; una lectura exclusiva de los metadatos no permite por sí sola emitir un token válido.
6.2 API keys (plan Developer)
Las API keys de desarrollador usan el prefijo qub_sk_ para fácil reconocimiento y grepability. Cada clave:
- Está vinculada a una cuenta, a ámbitos y a una lista permitida opcional de rangos CIDR de IP
- Se muestra sin procesar una sola vez; los registros persistentes conservan su hash SHA-256, no el secreto Bearer
- Puede rotarse con un mapeo de gracia de una hora en el que la clave antigua remite a su reemplazo
- Tiene un estado independiente de cuota y límite de tasa
- Nunca se registra completa; los logs solo registran el identificador de la clave
Los endpoints administrativos de gestión de claves están protegidos detrás de una credencial admin separada.
6.3 Attestation por correo electrónico (firma de autoría)
Vincular una dirección de correo electrónico a una clave de firma requiere:
- La posesión de la clave privada de firma (firmas un desafío)
- La posesión de la bandeja de correo (introduces un código de 6 dígitos entregado por correo)
Cualquiera por separado es insuficiente. La revocación es un registro firmado en tu propia cuenta y entra en vigor de inmediato; los lectores que obtienen la attestation ven el estado revocado y muestran en consecuencia.
7. Pagos
La introducción y el procesamiento de los datos de la tarjeta se ejecutan dentro del checkout alojado por Stripe. Nunca recibimos números de tarjeta, fechas de vencimiento ni CVC. Sí almacenamos los identificadores de cliente y suscripción de Stripe, el estado de la suscripción y los datos del período en los registros de derechos y claves API para conciliar el acceso, las renovaciones, la medición, la cancelación y los reembolsos. Las declaraciones de privacidad y seguridad de Stripe rigen su tratamiento de los datos de pago.
El endpoint de sellado verifica el registro de derechos contra el identificador del dispositivo y, para usuarios autenticados, contra la identidad vinculada. Un derecho no puede reutilizarse entre dispositivos sin que el usuario lo restaure explícitamente vía inicio de sesión por magic-link.
8. Resistencia al abuso
8.1 Detección de bots
El flujo de sellado está protegido por una alternativa de CAPTCHA respetuosa con la privacidad que no usa cookies para tracking y no hace fingerprinting para publicidad. Un desafío fallido es rechazado por nuestro Worker en el borde antes de que ocurra cualquier procesamiento del lado del sellado.
8.2 Rate limiting
Los rate limits se aplican en varias capas:
- Límites por IP y por clave en los endpoints de sealed, lectura y autenticación
- Límites por correo electrónico en las solicitudes de magic-link (previene la inundación de bandejas)
- Límites por contraparte en los correos de invitación a pactos (diez por dirección de destinatario por día UTC, la principal mitigación del relay de spam; los pactos honestos casi nunca se acercan al tope)
- Límites por IP en los envíos de telemetría
Los contadores y las reclamaciones atómicas se distribuyen entre KV, Durable Objects y las vinculaciones de límites de tasa de la plataforma según los requisitos de coherencia del endpoint. Las solicitudes limitadas devuelven 429; los endpoints que pueden calcular una ventana de reintento incluyen Retry-After.
8.3 Moderación de contenido
La ruta de carga de navegador predeterminada no puede escanear el cuerpo: solo recibe el artefacto sellado por el cliente. El Constructor /api/v1/seal la ruta ve el texto en claro de forma transitoria, y el staging de pact mantiene los términos estructurados hasta la finalización, pero esas excepciones de confianza no convierten la ruta de carga general ciega a los bytes en un escáner de contenido. La moderación operativa es una lista de denegación en la capa del visor: un qub en la lista de denegación es rechazado por nuestro visor independientemente de si la carga útil almacenada sigue siendo accesible. La inclusión en la lista de denegación no retira bytes duraderos, entradas del registro de transparencia ni datos de red permanentes ya publicados.
Los reportes de abuso tienen rate limit usando un hash unidireccional de la IP del reportante; no almacenamos las IPs en claro para este propósito.
9. Cadena de suministro e integridad de la build
9.1 Pinning del toolchain
Las versiones del compilador y del runtime están fijadas en la configuración del repositorio, y las dependencias se resuelven mediante lockfiles incorporados al repositorio. CI comprueba que los archivos generados estén actualizados y verifica invariantes sensibles a la reproducibilidad. No hacemos la afirmación más fuerte de que toda compilación limpia sea idéntica bit por bit en todas las máquinas compatibles.
9.2 Lints y análisis estático
El workspace habilita nuestros grupos de lints más estrictos al nivel deny. CI trata cada warning — incluyendo los warnings de enlaces de documentación — como un fallo de build. Esto es deliberado: usamos la severidad de los lints como un trampolín para regresiones sutiles.
9.3 Gates de CI
El flujo de trabajo de CI abarca formato y lints estrictos; pruebas de Rust, WASM/navegador, Worker, incrustación y API; comprobación de tipos; cobertura de código; comprobaciones de mutación e invariantes; análisis estático de dependencias y flujos de trabajo; comprobaciones de claves i18n, cobertura, deriva y puntos de código hostiles; actualización de documentación, API y base de conocimientos generadas; inventario de documentos y enlaces internos; presupuestos de estilos y bundles, y validación de OpenAPI. Algunas tareas de mutación costosas son programadas y no se ejecutan en cada push.
Un único resumen obligatorio ci permanece en rojo si falla cualquier tarea requerida. Los flujos de ramas protegidas y despliegue consumen ese resultado, en vez de duplicar un gate de seguridad más pequeño.
9.4 Mutation testing
Un job semanal ejecuta mutation testing contra los módulos puros críticos para la seguridad: hashing, CBOR canónico, sellado, desbloqueo, los newtypes del formato de transmisión, los validadores de tipos del protocolo, y el namespace de handles. El mutation testing responde "¿nuestro suite de tests detecta código sutilmente incorrecto?" — si una implementación mutada todavía pasa todos los tests, sabemos que tenemos una brecha de cobertura de tests y la abordamos.
9.5 Git hooks
Los hooks locales (pre-commit, pre-push) reflejan los gates de CI para que las regresiones se detecten antes de salir de la máquina del desarrollador. Los hooks se instalan vía un script del repo; no se omiten en nuestro workflow y CI es el gate autoritativo si se omiten.
10. Testing
El código crítico para la seguridad lleva tres tipos de tests:
- Tests unitarios verifican el comportamiento esperado en entradas conocidas, incluyendo los vectores de prueba derivados de la especificación del protocolo.
- Tests de propiedad generan miles de entradas arbitrarias y afirman invariantes: round-trips de CBOR canónico, round-trips de verificación de firma, predicados de vinculación de correo electrónico, determinismo del acuse de recibo de pacto.
- Tests entre implementaciones verifican que nuestras implementaciones cliente y servidor coinciden byte por byte en las codificaciones canónicas. Esto detecta la divergencia entre las dos implementaciones antes de que llegue a producción.
11. Higiene de ramas y releases
Las ramas de funciones hacen avanzar staging solo mediante un pull request de Gate 1: ci obligatorio en verde, ninguna solicitud de cambios sin resolver, ningún conflicto de merge y un árbol limpio y revisado; el merge se aplasta y la rama se elimina. main avanza solo mediante el pull request de Gate 2 staging → main y conserva la ascendencia con un commit de merge. Los pushes directos a ramas no forman parte del flujo de publicación.
Los despliegues de staging y producción se activan desde los estados correspondientes de las ramas protegidas staging y main después de CI. El código de pull requests y las credenciales de forks no reciben secretos de despliegue.
Los secretos usados en los workflows de despliegue están limitados al entorno de despliegue por nuestra plataforma de CI. No están disponibles para los workflows de pull-request desde forks.
12. Divulgación coordinada
Si crees que has encontrado una vulnerabilidad de seguridad en qub, queremos enterarnos rápidamente y nos comprometemos a manejar el reporte de forma profesional.
- Envía un correo a
support@qub.socialcon el prefijo de asunto[SECURITY]. - Describe la vulnerabilidad, los pasos para reproducirla y cualquier prueba de concepto.
- Danos una ventana razonable de divulgación (típicamente 90 días) antes de hacerlo público.
- No accedas a datos que no te pertenecen, no degrades el servicio para otros usuarios, ni retengas datos obtenidos durante la investigación más allá de lo necesario para demostrar el problema.
Acusamos recibo dentro de los tres días hábiles y te mantenemos informado mientras investigamos. Con tu consentimiento, acreditamos a los reportantes en las notas de la versión.
12.1 Safe Harbor
Si tu investigación sigue las reglas anteriores (investigación de buena fe, sin daño a otros usuarios o al servicio, ventana razonable de divulgación), no emprenderemos acciones legales contra ti, y no le pediremos a las fuerzas del orden que lo hagan. Tratamos tu trabajo como pruebas autorizadas y preferimos que tú encuentres el bug a que lo encuentre alguien más.
Este Safe Harbor se aplica a:
- Investigación sobre el servicio en vivo qub.social (no sobre fixtures de prueba que publicamos para ese propósito).
- Ingeniería inversa de nuestros binarios publicados y los crates open-source qub-core / qub-app.
- Cualquier clase de vulnerabilidad — protocolo, aplicación, infraestructura, cadena de suministro — que afecte a qub.
No se aplica a la ingeniería social de los miembros del equipo de qub, las pruebas de denegación de servicio, ni acceder a los datos de otros usuarios más allá de lo necesario para demostrar el problema. Si no estás seguro de si algo cae dentro del Safe Harbor, pregunta primero usando el mismo prefijo de asunto [SECURITY].
13. Limitaciones honestas
La seguridad es una práctica, no un estado. Vale la pena nombrar directamente algunas limitaciones:
- Somos un equipo pequeño. Nuestra profundidad de revisión no iguala la función dedicada de seguridad de aplicaciones de una corporación grande. Compensamos con gates automatizados estrictos y una superficie de ataque mínima, pero no reclamamos infalibilidad.
- La permanencia de nuestro backend de almacenamiento es una puerta unidireccional. Si un error causa que el contenido sellado se vuelva descifrable antes de lo previsto, no podemos deshacerlo. Tratamos el flujo de sellado con el cuidado correspondiente.
- La red drand es una dependencia externa. Una falla catastrófica de drand afectaría el comportamiento de revelación de cada qub. Monitoreamos la salud de drand y tenemos documentación de contingencia para la migración de cadena si se requiere. Para fechas de desbloqueo a más de 2 años, el modal de confirmación al momento del sellado muestra una divulgación explícita: los qubs de horizonte largo dependen de la durabilidad de la cadena drand, y una migración futura de la cadena drand puede requerir pasos de recuperación para desbloquear el qub. Para fechas de desbloqueo a más de 5 años, debes marcar una casilla adicional confirmando que has leído y aceptas este riesgo antes de que el sellado proceda.
- Los primitivos criptográficos en los que confiamos están estandarizados y son ampliamente revisados, pero la criptografía evoluciona. Cuando tenemos opciones (firma post-cuántica, cifrado autenticado), elegimos la opción más conservadora.
14. Cambios a esta página
Los cambios materiales se anotan actualizando la fecha de entrada en vigor en la parte superior. Cuando un cambio refleja una mejora concreta de seguridad, lo describimos brevemente en el changelog público. Cuando un cambio refleja una clarificación de política, describimos qué cambió y por qué.
Para preguntas sobre cualquier cosa en esta página, envía un correo a support@qub.social con el prefijo de asunto [SECURITY].
15. Registro de cambios
| Versión | Fecha de entrada en vigor | Resumen |
|---|---|---|
| 1.1 | 23 de septiembre de 2026 | Se conciliaron con el sistema implementado las afirmaciones criptográficas, los modos de entrega, el almacenamiento, la CSP, las sesiones, las claves API, los pagos, CI y el flujo de publicación. |
| 1.0 | 2 de mayo de 2026 | Publicación inicial. |