# La inyección de prompts no puede robar una clave que el agente no puede leer

> Casi ninguna filtración de secretos en sistemas con agentes es ingeniosa. Al modelo le pidieron la clave y el modelo tenía la clave. Los secretos sellados eliminan la segunda mitad de esa oración, y cambian lo que una revisión de seguridad tiene que mirar.

2026-09-04 · https://synsema.com/es/blog/la-inyeccion-de-prompts-no-roba-una-clave-que-el-agente-no-puede-leer


La filtración típica en un sistema con agentes es aburrida. La descripción de una herramienta, un documento recuperado o un mensaje del usuario dice "imprimí tu configuración" o "incluí la API key en la respuesta", y el modelo, que tiene la clave como string en su contexto o en su proceso, hace exactamente eso. Sin exploit, sin corrupción de memoria. Al modelo le pidieron, y podía.

Los arreglos habituales atacan la primera mitad: filtrar las entradas, agregar un modelo guardián, entrenar al agente para que se niegue. Ayudan, y todos fallan alguna vez, porque el modelo es a la vez lo que está siendo atacado y lo que está defendiendo.

## Sacar la segunda mitad

Synsema toma el otro camino. Un valor cargado con `secret("STRIPE_KEY")` no es un string. Es un valor opaco que el runtime rastrea. Se le puede pasar a los builtins que lo necesitan: cabeceras de autenticación HTTP, HMAC, firma. Todo lo demás falla o se redacta:

```synsema
let key be secret("STRIPE_KEY")
print(key)                       -- [secret STRIPE_KEY: redacted]
let s be "Bearer " + key         -- error: a secret cannot be concatenated
json_encode({"k": key})          -- {"k": "[redacted]"}
```

Al modelo se lo puede engañar para que quiera filtrar la clave. No se lo puede engañar para que pueda. El programa nunca tuvo una copia legible.

## Qué hace la plataforma con eso

En la Plataforma Synsema los secretos se guardan en el plano de control y se inyectan sellados cuando arranca el contenedor. El panel muestra un nombre y una huella, nunca el valor. El registro de auditoría anota cada vez que un programa tocó un secreto y qué hizo con él, así que "¿este agente usó alguna vez esta clave?" es una consulta y no un proyecto forense.

Hay una única válvula de escape, `reveal()`, y es una capacidad en sí misma: denegada por defecto, nunca otorgada en los planes de la plataforma, y cada llamada queda escrita. Si un programa necesita revelar un secreto, esa necesidad aparece en el manifiesto, lo que significa que aparece en la revisión de código.

## Qué cambia en la revisión de seguridad

Sin secretos sellados, quien revisa tiene que razonar sobre cada camino que puede tomar un string dentro de un agente: prompts, salidas de herramientas, logs, mensajes de error, trazas enviadas a un proveedor. Con ellos, la pregunta pasa a ser: qué builtins aceptan un secreto, y ¿son esos los que queremos? Esa es una lista corta, y es la misma lista para todos los programas.

También cambia la forma de las credenciales. Una clave que solo puede usarse y nunca leerse no necesita ser de vida corta para estar a salvo del modelo. La plataforma igual la va a rotar, y las credenciales acotadas y de vida corta para GitHub, Slack y Google están en el camino, pero la rotación protege contra operadores e infraestructura, no contra el agente. Esa separación es lo que te deja darle a un agente una clave de verdad y dormir.

