CCDV-F · Seguridad
Guardrails en capas, mínimo privilegio y hooks que frenan lo destructivo
Un tutor de idiomas público tiene una sola defensa: un system prompt que describe la política y le pide al modelo que rechace lo indebido. Algunas cuentas insisten con trucos de rol y a veces consiguen algo. En otro equipo, Claude Code hizo un force push escrito como git push origin main -f, que ninguna regla de denegación cubría. Los dos casos tienen la misma falla: un único control, y blando.
Guardrails en capas
Ningún control es perfecto, así que se suman varios independientes. Eso son los guardrails en capas (guardrail layering):
| Capa | Qué hace |
|---|---|
| Filtro de entrada | Un modelo liviano (Haiku) clasifica cada mensaje y devuelve un veredicto estructurado antes de que llegue al modelo principal |
| System prompt | Describe la política de contenido (content policy) y qué hacer ante un pedido fuera de ella |
| Validación de salida | Revisa la respuesta antes de mostrarla o de ejecutar algo con ella |
| Mínimo privilegio | El agente no tiene acceso a lo que no necesita, así que un error o una manipulación no puede hacer daño grande |
| Monitoreo | Registra rechazos por cuenta y limita o suspende a quien insiste en saltarse la política |
Subir la temperatura o usar un modelo más grande no es una capa: no controla nada.
Seguridad desde el diseño
La seguridad desde el diseño (secure by design) decide los accesos antes de escribir el primer prompt:
- Identidad y accesos propios del agente: un rol de base de datos de solo lectura sobre las tres vistas que necesita, no la cuenta de administrador con una regla “solo SELECT” en el prompt.
- Privacidad: los datos personales no entran al contexto si la tarea no los necesita.
- Aislamiento: el código que genera el modelo corre en un entorno sin acceso a producción.
- Aprobación humana solo donde importa: pedir confirmación para cada consulta frena el trabajo y la gente termina aprobando sin leer.
Hooks para lo que tiene que pasar siempre o nunca
Un hook es código que el harness ejecuta en un momento fijo, sin depender de que el modelo se acuerde de nada. En Claude Code se configura en settings.json (el del proyecto se versiona y se revisa como código), y el Agent SDK ofrece los mismos eventos para tus propias aplicaciones.
El hook previo a la herramienta (PreToolUse hook) corre antes de cada llamada y recibe tool_name y tool_input, por ejemplo el comando completo de Bash. Puede bloquear de dos formas:
- salir con código de salida 2 (exit code 2): la llamada se bloquea y el texto de stderr le llega a Claude como motivo; ni siquiera una regla
allowla deja pasar; - devolver JSON con
permissionDecision: "deny"y un motivo.
Con un matcher (Bash, Edit|Write) elegís a qué herramientas aplica. El hook puede parsear el comando y reconocer todas las variantes de un force push o de un rm -rf, algo que una lista de cadenas exactas en las reglas de denegación no logra.
PostToolUse corre después: sirve para auditar, formatear o avisarle a Claude del resultado, pero no puede impedir algo que ya pasó.
Una instrucción en CLAUDE.md o en el system prompt es una guía que el modelo sigue casi siempre. Si algo no puede pasar nunca, va en un hook o en un permiso.
Las trampas típicas
- Un system prompt como única defensa.
- Pedirles a los usuarios que no intenten trucos.
- Darle al agente la cuenta de administrador y “pedirle” que no escriba.
- Reglas de denegación con cada forma de escribir un comando que se te ocurra.
- Aprobación manual de cada comando en lugar de bloquear lo destructivo.
- Repetir la regla en mayúsculas en CLAUDE.md.
En el examen
Si el escenario tiene una sola defensa blanda, buscá la opción que suma capas independientes (filtro previo, monitoreo, validación). Si un agente tiene más acceso del que usa, buscá un rol acotado. Y si hay una acción que no puede pasar nunca en un agente con terminal, buscá un hook PreToolUse que la bloquee.
Pregunta rápida
Una pregunta del simulacro sobre este dominio. Cuenta para tu progreso.
A fitness company shipped a mobile app whose writing-coach feature calls the Claude API directly from the device. The API key is embedded in the app bundle so the feature could ship without a backend change, and the release went out in a hurry before a marketing campaign.
Two weeks later, usage on the key has tripled while daily active users stayed flat, and requests arrive from IP ranges the company does not recognize. The team cannot tell which requests come from real users and which do not, and the next campaign starts in a month.
What should the team do?