TOCTOU en tool calling: por qué un permission check no basta
Un agente que puede editar archivos, ejecutar comandos o llamar herramientas necesita decidir, en algún punto, si una acción está permitida. La forma obvia de hacerlo es revisar el permiso antes de ejecutar la acción. El problema es que “antes” y “durante” no son el mismo instante, y en ese hueco puede pasar cualquier cosa: un symlink que cambia de destino, un path que se resuelve distinto la segunda vez, una autorización que ya no refleja el estado actual. Esto se llama TOCTOU (time-of-check-time-of-use) y es un bug clásico de sistemas Unix, no algo nuevo de la era de los agentes. Lo que sí es nuevo es la superficie: ahora el “check” lo hace un harness de agente y el “use” lo dispara un modelo que decide qué tool llamar.
Esta semana, Claude Code v2.1.251 corrigió cuatro variantes del mismo problema en una sola release:
- Read, Write y Edit seguían un symlink que había sido cambiado de destino después de pasar el chequeo de permisos, lo que permitía leer o escribir fuera del directorio aprobado.
- Los comandos de plugins declarados en un marketplace podían apuntar fuera del directorio del plugin; ahora se rechazan con un error de path traversal.
- El Workflow tool leía (y citaba en errores) un
scriptPathfuera de lo que la sesión puede leer, antes de que el chequeo de permisos corriera. - Grep y Glob no aplicaban las reglas
Read(...)de deny a archivos alcanzados a través de un path de búsqueda symlinkeado.
Cuatro bugs distintos en el código, un solo patrón de diseño: el chequeo pasa una vez y el acceso real ocurre después, sobre un recurso que ya no es necesariamente el mismo.
Codex encuentra la misma clase de bug en su capa de autorización
En paralelo, Codex rust-v0.151.0 corrigió que clasificaciones de Guardian (su sistema de permisos) quedaran vigentes y siguieran autorizando acciones después de que el estado de permisos había cambiado. Es la misma familia de bug que los symlinks de Claude Code, aplicada a una cache de decisiones en vez de a un path: la autorización se calculó en un momento, pero se sigue usando después de que las condiciones cambiaron.
La misma release de Codex también mejoró la aplicación del sandbox remoto para usar el home directory, el sistema operativo y las convenciones de rutas reales del ejecutor, en vez de asumirlas, lo que es otra forma del mismo problema: verificar contra un modelo del entorno que puede no coincidir con el entorno real en el momento de ejecutar.
El otro borde del boundary: qué le llega al modelo desde la tool
Hay una segunda mitad de este mismo problema que no es TOCTOU pero vive en el mismo límite: qué tan confiable es lo que una tool devuelve o filtra hacia el modelo o el cliente.
Codex rust-v0.151.0 agregó que extensiones puedan inspeccionar o reemplazar el resultado de una tool MCP antes de que llegue al modelo, reconociendo que el output de una tool es tan poco confiable como su input. El MCP Python SDK v2.1.0, por su parte, cambió que una excepción sin capturar en un handler de tool, resource o prompt ya no exponga el traceback al cliente: ahora solo se ve “Error executing tool ToolError o ResourceError explícitamente. Antes, un error interno del servidor podía filtrar detalles de implementación directo al modelo o al cliente sin que nadie lo decidiera.
Y en una capa distinta, google/adk-python 2.8.0 agregó guardas contra inyección SQL en las tools de BigQuery, que es el recordatorio de que el tool calling también hereda los problemas de siempre: si una tool arma una query con input del modelo sin sanitizar, no importa cuán bien resuelto esté el permission check de arriba.
Reglas para tu propio harness
Si construyes o extiendes un harness de agentes, esta semana deja un checklist concreto:
- Cualquier lugar donde resuelvas un path o una autorización y guardes el resultado para usarlo después, revísalo por TOCTOU: symlinks, cambios de working directory, o simplemente el tiempo que pasa entre el chequeo y la ejecución.
- No confíes en una decisión de autorización cacheada entre turnos o entre llamadas si el estado de permisos pudo haber cambiado en el medio.
- Trata el output de una tool con la misma sospecha que el input: sanitiza antes de que llegue al modelo, y decide explícitamente qué de un error interno es seguro exponer.
- Si tu harness soporta plugins o marketplaces de terceros, valida que cualquier path declarado por esos paquetes se resuelva dentro de su propio directorio, no fuera de él.
Fuentes:
Seguir leyendo
Esto se demuestra en video, y se sigue a diario en la comunidad
Las demos completas van al canal. El seguimiento release por release, adentro.