ExplicacionSeguridad

Modelo de amenazas

Qué protege Styx, dónde están las fronteras de confianza y cómo se reparte la seguridad entre data plane, control plane y comunicaciones.

Implementado en parte. El diseño es de dec-0117, dec-0118 y dec-0119, que se auditan juntos. Cuánto de cada invariante está verificado es estado de gate: se lee en la vista generada de track/byte-runtime/sec y de track/identity/sec, nunca en esta página.

Principio

Seguridad por diseño, con defensa en profundidad: un bug que no escale tiene que ser imposible de escalar. Tres decisiones, que forman un único modelo de amenazas, lo reparten:

DecisiónÁmbito
dec-0117Data plane Zig: daemon, parsers, libav, ficheros, contenedores
dec-0118Control plane TS y web: identidad, sesiones, autorización, CSRF, CSP, errores, auditoría
dec-0119Comunicaciones: todo lo que cruza un proceso pasa por spire

Cada una lleva su STRIDE por frontera y, por cada invariante, un test que falla si alguien lo rompe.

Qué se protege

  • La biblioteca del usuario y, sobre todo, todo lo que hay fuera de las raíces (el host, los secretos, /proc): el daemon tiene a la vez ficheros y red, así que es el componente cuya integridad más importa.
  • Las claves de firma: la de capacidades sólo la tiene playback-svc; las de identidad, identity-svc. El daemon sólo guarda claves públicas.
  • Las credenciales de sesión de los usuarios y los secretos de las fuentes.
  • La disponibilidad: CPU, ancho de banda, memoria y descriptores, por usuario y global.
  • La telemetría: no filtra tokens, rutas ni identificadores de actor en claro.

Fronteras de confianza

Lado no confiableFrontera
Todo lo que llega por la red al daemoncliente ↔ daemon (QUIC, WebTransport, MoQT, HTTP/3)
El proceso local hasta que se autenticacontrol plane ↔ daemon por el socket de control
Respuestas y bytes remotosdaemon ↔ fuentes remotas
El contenido de un fichero, aunque sea localbytes de un fichero ↔ parsers (MP4, Matroska, subtítulos)
Según el nivel de confianza del pluginplugins ↔ núcleo
La entrada que libav interpretadaemon ↔ libav
Symlinks, renombrados y montajesdaemon ↔ sistema de ficheros
El propio proceso si ya está comprometidocontenedor ↔ host
El broker y los demás clientes del busdaemon ↔ NATS
El navegador, su contenido remoto (metadatos, imágenes, subtítulos)navegador ↔ BFF y contenido remoto ↔ DOM

El detalle por frontera (amenaza y mitigación) está en dec-0117 §3 y dec-0118 §1.

Cómo se distribuye la defensa

  1. Capa de biblioteca. zkit.safety impone los invariantes: handles con generación, presupuestos, raíces fd-relativas, lectores acotados. Ver data plane.
  2. Capa de construcción. Guardas que impiden saltarse la capa 1: zig build audit:safety sobre el AST de Zig, check:no-media-spawn, tests de arquitectura sobre imports del bus. Cada guarda demuestra su rama roja con un mutante.
  3. Capa de despliegue. Contenedores sin privilegios, rootfs de sólo lectura, secretos en ficheros, identidades y ACL de NATS por servicio, Postgres y Valkey con un rol por servicio.
  4. Capa de política. Toda ruta HTTP y todo handler del bus declara su policy, y deniega si falta. Un único motor de autorización (@styx/authz) evalúa can(principal, acción, recurso). Ver sesiones y BFF y comunicaciones.

Auditoría continua (AppSec)

La seguridad no se da por cerrada al escribir el diseño. Una pasada AppSec repite un ciclo por área (transportes Zig, núcleo Zig, SDK, servicios TS, web, despliegue y cadena de suministro):

  1. un auditor busca con un exploit concreto y fichero:línea, sin editar;
  2. un verificador distinto intenta refutar cada hallazgo y ajusta su severidad;
  3. un arreglo por hallazgo, con test rojo antes y verde después, y mutantes;
  4. un integrador distinto hace el merge y vuelve a pasar las suites completas.

El criterio es «hasta que una pasada salga seca», y los informes dicen con honestidad cuándo no ha ocurrido. El informe de cada pasada vive en docs/reviews/, y la evidencia por nodo en docs/track/<nodo>/sec/evidence/.