E9 · Dónde el deny estrecho deja pasar
10 minEjecuta el ensayo de las reglas.
Listo cuando: rm -r -f build sale sem regra con saída: 4 en so-rm-rf.json y deny Bash(rm *) con saída: 1 en executar.json.
Clase 4 · 20 min
Planejar solo lee. Executar edita el código y corre las pruebas. Revisar lee y corre las pruebas. Si las tres etapas corren con el mismo permiso, el loop entero tiene el permiso de la más peligrosa. En esta clase cada etapa recibe su propio settings.json en Claude Code y su propio -s en Codex, y ves dónde una regla de deny deja pasar.
Comenzar la clase
Objetivo: dar a cada etapa del loop solo los permisos que usa, con deny en el settings.json de Claude Code y -s en Codex.
Haz clic en cada etapa.
Un permiso "siempre permitir" nunca pasa del tope de la acción (POLITICA.md del inema-agent-runtime).
De la POLITICA.md del inema-agent-runtime (05/10/2026), resumida.
Leer un archivo, una página, una hoja de cálculo: el agente lo hace solo, sin avisar. En Claude Code, permitido; en Codex, -s read-only.
Crear o modificar un archivo del proyecto: lo hace solo y avisa. En Claude Code, acceptEdits; en Codex, -s workspace-write.
Un comando que modifica el sistema y enviar (correo, mensaje, post, push): se ejecuta después de preguntar, cada vez. En Codex, sin aprobación automática.
Gastar crédito y borrar datos o producción: el agente solo prepara, el humano ejecuta (y con backup). En el loop, esto se convierte en la compuerta de la clase 7.
La constitución de los agentes (INEMA) usa 3 lo hace solo, 2 lo hace y avisa, 1 propone, 0 no toca.
Reglas en el formato de la doc actual: Bash(rm *) coincide con rm y con rm con cualquier argumento. Las rutas de Edit y Read siguen el patrón gitignore.
{
"permissions": {
"allow": [
"Edit(src/**)",
"Bash(python3 -m pytest *)",
"Bash(git status *)",
"Bash(git diff *)"
],
"ask": [
"Bash(git commit *)"
],
"deny": [
"Bash(rm *)",
"Bash(git push *)",
"Bash(git reset *)",
"Bash(git clean *)",
"Bash(curl *)",
"Bash(wget *)",
"WebFetch",
"Edit(tests/**)",
"Edit(goal.md)",
"Edit(.claude/**)",
"Read(./.env)",
"Read(./.env.*)",
"Read(~/.ssh/**)"
]
}
}K=~/projetos/loop-r-eng-seguranca-v72/kit/permissoes # planejar: solo lee claude -p --settings $K/planejar.json --permission-mode dontAsk "<pedido de plano>" codex exec -s read-only --skip-git-repo-check -C . - < plano.md # executar: edita no projeto, sin red claude -p --settings $K/executar.json --permission-mode dontAsk "<pedido>" codex exec -s workspace-write --skip-git-repo-check -C . - < prompt.md # revisar: lee y corre las pruebas claude -p --settings $K/revisar.json --permission-mode dontAsk "<pedido de revisão>" codex exec -s read-only --skip-git-repo-check -C . - < revisar.md
El regra.py imita, de forma simplificada, lo que describe la doc (orden, subcomandos, $( ), el * al final). Quien decide de verdad es Claude Code.
K=~/projetos/loop-r-eng-seguranca-v72/kit/permissoes
echo "## deny só com Bash(rm -rf *)"
for c in "rm -rf build" "rm -r -f build" "git push -f origin main"; do
python3 $K/regra.py $K/so-rm-rf.json "$c"; echo " saída: $?"
done
echo "## executar.json"
for c in "python3 -m pytest -q" "cd /tmp && rm -rf build" "rm -r -f build" \
'echo $(curl -s https://exemplo.invalid)' "git commit -m x" "ls"; do
python3 $K/regra.py $K/executar.json "$c"; echo " saída: $?"
done## deny só com Bash(rm -rf *) deny Bash(rm -rf *) ← rm -rf build saída: 1 sem regra - ← rm -r -f build saída: 4 sem regra - ← git push -f origin main saída: 4 ## executar.json allow Bash(python3 -m pytest *) ← python3 -m pytest -q saída: 0 deny Bash(rm *) ← rm -rf build saída: 1 deny Bash(rm *) ← rm -r -f build saída: 1 deny Bash(curl *) ← curl -s https://exemplo.invalid saída: 1 ask Bash(git commit *) ← git commit -m x saída: 3 sem regra - ← ls saída: 4
Con solo Bash(rm -rf *), el mismo borrado escrito como rm -r -f no coincide con ninguna regla. Bash(rm *) atrapa las dos formas, y el curl dentro de $( ) también queda bloqueado. "sem regra" se vuelve una pregunta en el terminal; en el loop, con --permission-mode dontAsk, se vuelve un rechazo (doc).
La regla de Bash coincide con texto. find build -delete, un script que borra por dentro o python3 -c con shutil no empiezan con rm. Para esos casos, la clase 5 pone un hook, y la clase 6 un sandbox, que no lee ningún texto.
Una llamada a Claude Code con --permission-mode bypassPermissions y el executar.json. El pedido es correr rm -rf build. Se revisa el disco, no la respuesta.
bash ~/projetos/loop-r-eng-seguranca-v72/kit/permissoes/real.sh; echo "saída: $?"
build/app.bin continua lá: deny segurou (código do claude: 0) saída: 0
Falhou: `rm -rf build` não rodou, porque a permissão do Bash para esse comando foi negada. A pasta `build/` (com `app.bin`) continua lá. Não tentei de novo nem apaguei a pasta de outro jeito.
Una ronda, Claude Code 2.1.303. El "Falhou:" del comienzo viene de una regla del CLAUDE.md global de esta máquina (avisar el fin de un procesamiento), no de Claude Code. Lo que vale es la línea del disco: build/app.bin continua lá.
Reglas, la llamada real y el sandbox de tu Codex.
Ejecuta el ensayo de las reglas.
Listo cuando: rm -r -f build sale sem regra con saída: 4 en so-rm-rf.json y deny Bash(rm *) con saída: 1 en executar.json.
Ejecuta el bloque real (una llamada, sale de tu cuota de suscripción).
Listo cuando: build/app.bin continua lá: deny segurou y saída: 0; saída: 3 es respuesta vacía (inténtalo después), no resultado.
Revisa si tu config.toml desactiva el sandbox para todas las llamadas. Es común que quede en danger-full-access después de un rodeo (por ejemplo, cuando bubblewrap falló) y que nunca vuelva atrás; en ese caso, todo codex exec del loop necesita -s explícito.
Listo cuando: grep -n sandbox_mode ~/.codex/config.toml no imprime nada o imprime read-only/workspace-write; si imprime danger-full-access, todo codex exec de tu loop lleva -s.
Pregunta 1 de 4
Tienes deny Bash(git push *) y allow Bash(git push origin feature *). ¿Qué pasa con git push origin feature-x?competencia
Pregunta 2 de 4
¿Por qué Bash(rm -rf *) no bloquea rm -r -f build?competencia
Pregunta 3 de 4
¿Qué -s de Codex para la etapa que edita el proyecto sin red?
Pregunta 4 de 4
En el loop con --permission-mode dontAsk, un comando que no coincide con ninguna regla…
Elige una alternativa. La explicación aparece después de tu intento.