Ir al contenido

Modelo de seguridad

WhyStack pide acceso de lectura privilegiado a todo tu stack. Para una herramienta así, la transparencia es un requisito y no una cortesía, y por eso esta mitad es abierta. Lo que sigue es lo que el código garantiza de verdad, y dónde.

El control-plane pregunta qué. El runner decide si puede. Esa decisión vive en exactamente un lugar, apps/runner/src/enforcement.ts, y hace tres cosas:

  1. Allowlist del catálogo. Solo operaciones del catálogo versionado. Cualquier cosa fuera de él se rechaza, sin importar lo que pida el control-plane.
  2. Argumentos estrictos. Se validan contra el inputSchema de la operación, en modo estricto.
  3. Deadline. Se aplica por operación (RUNNER_INVOKE_DEADLINE_MS, por defecto 30 s).

Que la decisión viva del lado del runner es justamente el punto: un control-plane comprometido no puede pedir una operación que el catálogo no tiene.

El catálogo es de solo lectura salvo por seis operaciones, todas en sistemas de registro (tickets, chat e issues):

Operación Servicio
tickets.createIssue Jira
tickets.addComment Jira
tickets.transitionIssue Jira
tickets.createGithubIssue GitHub (solo abrir un issue)
chat.postMessage Slack
chat.createChannel Slack

AWS, GCP, Magalu, Datadog y todo lo demás siguen siendo estrictamente de solo lectura. En GitHub, la única escritura es abrir un issue: ni pull request, ni comentario, ni push.

Ese conteo lo impone un test, no una convención: el CI enumera las operaciones marcadas como escritura en el catálogo y falla, nombrando la operación, si el conjunto deja de ser exactamente estas seis, o si alguna de ellas sale de tickets y chat. El test existe porque la marca de escritura queda deliberadamente fuera del hash del catálogo (es comportamiento aditivo del runner: un Agent más antiguo que no la conoce sigue exigiendo la confirmación del lado del control-plane), y sin él, marcar una operación de AWS o de Datadog como escritura no rompería ninguna guarda. Del lado de la superficie de agente está el test espejo, sobre las cinco tools de escritura.

La confirmación humana es defensa en profundidad, aplicada de los dos lados:

  • Control-plane: el gate confirmed y el preview viven en la tool de escritura.
  • Runner: independientemente de eso, el runner exige confirmed: true en la invocación para ejecutar cualquier operación marcada como write en el catálogo. Sin eso, responde op_not_authorized.

El segundo existe justamente para no depender del primero. Es un gate a nivel de wire.

Tres operaciones aceptan consultas libres: la agregación de MongoDB, Athena y CloudTrail Lake. Salieron con validación de seguridad de escritura en el handler, no por confianza:

  • Los pipelines de agregación que contienen $out o $merge se rechazan.
  • El SQL que contiene DDL o DML se rechaza.

El ConnectorRuntime sostiene cuatro garantías. Vale la pena ser preciso sobre cuáles se aplican de verdad y cuáles apenas se declaran:

Garantía native sidecar
Secretos con alcance por connector aplicada aplicada
Allowlist de egress declarativa aplicada
Conformidad con el contrato aplicada (en tests) aplicada
Redacción de campos declarados aplicada aplicada

El runner es un cliente de salida, y punto. No escucha en ningún puerto, no expone ningún endpoint de health (la señal de salud es un archivo local, leído por exec dentro del contenedor), y no necesita nada abierto en tu firewall para tráfico de entrada. El túnel es WSS reverso con mTLS, y el certificado viene de un enrollment cuya identidad prueba la plataforma.

La inteligencia de diagnóstico es cerrada y vive en el control-plane. Eso importa para tu evaluación de riesgo de dos maneras:

  • A favor: todo lo que toca tus credenciales está aquí, auditable. El ejecutor es la superficie que importa para la seguridad, y es abierta.
  • En contra: no puedes auditar lo que el control-plane hace con los resultados ya redactados que recibe.

Las dos cosas son honestas de decir.

Algunos puntos de partida útiles si estás revisando el código:

Pregunta Dónde mirar
¿Qué se puede ejecutar? packages/protocol, el catálogo versionado.
¿Qué se rechaza, y cómo? apps/runner/src/enforcement.ts.
¿Qué se redacta? apps/runner/src/redact/ y packages/core-edge/src/policy/.
¿Cómo se prueba la identidad? apps/runner/src/enroll/attestation.ts.
¿Qué credencial pide cada connector? apps/runner/src/connectors/manifests/real.ts.