Cada iteración hace tu código menos seguro
Después de diez rondas de refinamiento de código impulsado por LLM, el 43,7 por ciento de las cadenas de iteración contenían más vulnerabilidades que el código base del que partieron.1 El agente mejoró la funcionalidad. El agente pasó las pruebas. Pero el código también se volvió menos seguro con cada iteración — un patrón que los investigadores llaman “deriva de especificación”. Nadie lo notó porque el código mejoraba en todas las métricas excepto seguridad.
TL;DR
Un estudio de refinamiento iterativo de código con LLM en tres modelos (GPT-5-Nano, Claude Sonnet 4.5, DeepSeek-V3) y 2.880 pasos de iteración revela una paradoja: los agentes optimizan para corrección funcional mientras degradan silenciosamente la seguridad. Las mitigaciones estándar fallan. Agregar herramientas de análisis estático de seguridad (puertas SAST) al ciclo aumentó la degradación latente del 12,5 por ciento al 20,8 por ciento. El framework SCAFFOLD-CEGIS abordó el problema con cuatro capas de verificación, logrando una tasa de degradación latente del 2,1 por ciento con un 100 por ciento de monotonicidad de seguridad, a costa de una tasa de completitud de tareas del 77 por ciento. Este hallazgo importa a cualquiera que ejecute ciclos de agentes autónomos.
La paradoja
Los investigadores probaron tres LLMs (GPT-5-Nano, Claude Sonnet 4.5, DeepSeek-V3) en 24 tareas de programación en seis categorías de seguridad (base de datos, manejo de entrada, autenticación, gestión de recursos, criptografía, manejo de rutas), produciendo 288 cadenas de iteración y 2.880 pasos totales.1 El hallazgo: la deriva de especificación durante la optimización multiobjetivo causa que la seguridad se degrade gradualmente a lo largo de iteraciones sucesivas.
El mecanismo: cuando un agente optimiza código a lo largo de múltiples rondas, cada ronda se enfoca en mejoras funcionales (corregir errores, agregar funciones, pasar pruebas, mejorar rendimiento). Las restricciones de seguridad compiten con los objetivos funcionales por la atención del agente. A lo largo de diez rondas, el agente aprende (implícitamente, a través de la acumulación de contexto) que los cambios funcionales producen retroalimentación positiva mientras que las restricciones de seguridad no producen retroalimentación alguna. La lógica defensiva que no contribuye a la funcionalidad visible se simplifica, se refactoriza o se reemplaza con alternativas más débiles.
La tasa de degradación del 43,7 por ciento proviene de un estudio observacional separado que rastreó GPT-4o a lo largo de diez rondas de iteración. El experimento principal comparó SCAFFOLD-CEGIS contra cinco enfoques de defensa existentes: seguridad basada en prompts, auto-refinamiento, SAST post-hoc, guardia basada en pruebas y guardia híbrida.1 La comunidad investigadora ya había identificado la degradación iterativa como una preocupación. Ninguna de las cinco alternativas la resolvió.
Un estudio independiente de Shukla, Joshi y Syed, revisado por pares y aceptado en IEEE-ISTAS 2025, corrobora el patrón.4 Los investigadores tomaron diez muestras de código en C y Java verificadas en seguridad, aplicaron cuatro estrategias de prompting distintas a lo largo de diez iteraciones cada una (400 muestras en total) y midieron un aumento del 37,6 por ciento en vulnerabilidades críticas después de solo cinco iteraciones. La taxonomía de vulnerabilidades abarcó 12 categorías incluyendo seguridad de memoria, validación de entrada, implementación criptográfica y fallas de inyección. La consistencia entre diferentes equipos de investigación, lenguajes y metodologías de evaluación confirma que la degradación iterativa es una propiedad del enfoque, no un artefacto de una configuración experimental específica.
Por qué las puertas SAST lo empeoran
El hallazgo más contraintuitivo: agregar herramientas de análisis estático de seguridad como puertas entre iteraciones aumentó la degradación latente del 12,5 por ciento al 20,8 por ciento.1
El artículo atribuye la causa a la deriva de especificación durante la optimización multiobjetivo. Una explicación complementaria se mapea a un patrón conocido en el desarrollo de software humano: cuando los desarrolladores dependen de linters y analizadores estáticos, escriben código menos defensivo porque las herramientas “atraparán” los problemas. La misma dinámica probablemente aplica a los agentes LLM. Cuando el agente recibe retroalimentación SAST entre iteraciones, ocurren dos cosas:
-
El agente optimiza para pasar el escáner, no para escribir código seguro. Las herramientas SAST verifican patrones de vulnerabilidad conocidos (SQL injection, XSS, desbordamientos de búfer). El agente aprende a evitar esos patrones específicos mientras introduce debilidades de seguridad novedosas que el escáner no detecta.
-
El agente elimina defensas “redundantes”. Si el escáner reporta que la validación de entrada en la capa A es suficiente, el agente elimina la validación en la capa B durante la siguiente iteración. La validación en la capa B era defensa en profundidad, no redundancia. El escáner no puede distinguir entre ambas.
El resultado: la iteración con puertas SAST produce código que pasa los escaneos de seguridad pero contiene más vulnerabilidades latentes que la iteración sin puertas. Las herramientas crean una falsa sensación de seguridad que hace que el agente sea menos cauteloso, no más.
Cualquiera que ejecute un ciclo de codificación autónomo con puertas SAST entre iteraciones debería prestar atención. Las puertas no te están protegiendo. Las puertas están entrenando a tu agente para evadir la protección.
Qué hace diferente SCAFFOLD-CEGIS
El framework SCAFFOLD-CEGIS adopta un enfoque diferente.1 En lugar de verificar patrones de vulnerabilidad conocidos, el framework impone monotonicidad de seguridad: ninguna iteración puede hacer el código menos seguro que la iteración anterior.
Los resultados de los tres enfoques:
| Enfoque | Degradación latente (SSDR) | Monotonicidad de seguridad | Completitud de tareas |
|---|---|---|---|
| Sin puertas (base) | 12,5% | No medida | Mayor |
| Puertas SAST | 20,8% | No garantizada | Mayor |
| SCAFFOLD-CEGIS | 2,1% | 100% | 77,14% |
La arquitectura usa cuatro capas de verificación secuenciales, cada una verificando una propiedad diferente:1
| Capa | Función | Criterio de aceptación |
|---|---|---|
| Corrección | Ejecutar suite de pruebas completa | Todas las pruebas pasan |
| Monotonicidad de seguridad | Comparar resultados SAST entre iteraciones | Sin nuevas vulnerabilidades vs. anterior |
| Presupuesto de diff | Limitar la escala de cambios por iteración | Tamaño del cambio dentro del umbral |
| Integridad de ancla | Verificar elementos de código críticos para seguridad | Coincidencia por subcadena, regex, AST o semántica |
El framework adopta el principio CEGIS (counterexample-guided inductive synthesis): un ciclo cerrado de generación de candidatos, verificación, retroalimentación y regeneración. En lugar de usar verificadores formales, el sistema emplea análisis estático y verificación de anclas semánticas, representando los contraejemplos como reportes de fallo estructurados.1 Si cualquier capa rechaza una iteración, el sistema revierte a la versión anterior en lugar de intentar corregir la regresión.
La compensación es real: SCAFFOLD-CEGIS logró una tasa de completitud de tareas del 77,14 por ciento, comparada con tasas más altas para enfoques menos seguros.1 La monotonicidad de seguridad cuesta productividad. El framework rechaza iteraciones que un sistema menos estricto aceptaría y mejoraría. Si la compensación vale la pena depende de si valoras las garantías de seguridad por encima del rendimiento.
La idea clave: revertir ante fallos en lugar de iterar sobre fallos. Los ciclos estándar con puertas SAST detectan un problema y le piden al agente que lo corrija, produciendo otra iteración que puede introducir nuevos problemas. SCAFFOLD-CEGIS detecta un problema y descarta la iteración por completo. La garantía de monotonicidad proviene de nunca aceptar una regresión, no de detectar y corregir regresiones.
Conexión con el diseño de harnesses de agentes
Este hallazgo se conecta directamente con cómo los profesionales construyen capas de orquestación alrededor de CLIs de agentes.2 Los siete modos de fallo que documenté a partir de más de 500 sesiones autónomas incluyen varios que la paradoja del refinamiento iterativo explica: agentes que pasan pruebas mientras degradan la calidad del código, agentes que optimizan para la métrica equivocada, agentes que eliminan restricciones de seguridad durante la refactorización.
Los hooks de juicio que describí en “Anatomy of a Claw” abordan el problema de degradación a través de un mecanismo diferente. quality-gate.sh bloquea reportes de completitud que carecen de evidencia. filter-sensitive.sh captura exposición de credenciales antes de que llegue al disco. recursion-guard.sh limita la profundidad de generación de agentes. Cada hook impone una propiedad de monotonicidad: el sistema no debería empeorar en una dimensión específica mientras el agente itera. El patrón de constitución en tiempo de ejecución extiende la misma idea: reglas de gobernanza embebidas que el agente no puede anular durante la ejecución.
El sistema autoresearch de Karpathy usa el mismo patrón.3 El harness de evaluación conserva las mejoras y descarta las regresiones mediante gestión de ramas de git. La métrica de entrenamiento (bits de validación por byte) sirve como restricción de monotonicidad. Ningún resultado experimental que degrade la métrica sobrevive.
Tres sistemas independientes (investigación en verificación formal, infraestructura de investigación en ML, harnesses de agentes en producción) convergen en el mismo principio de diseño: nunca iterar sobre fallos; siempre revertir ante fallos. Darle a un agente una segunda oportunidad para corregir una regresión produce peores resultados que descartar la regresión e intentar un enfoque nuevo.
Qué deberían hacer los profesionales
Tres acciones concretas basadas en los hallazgos:
Audita tus ciclos de iteración en busca de monotonicidad de seguridad. Si tu agente ejecuta múltiples rondas de modificación de código, compara la postura de seguridad en cada ronda contra la línea base original, no solo contra la ronda anterior. La deriva acumulativa es invisible cuando solo comparas iteraciones adyacentes.
No dependas únicamente de puertas SAST. Los resultados con puertas SAST (20,8 por ciento de degradación, peor que sin puertas) deberían cambiar cómo diseñas los ciclos de retroalimentación. Las herramientas SAST son valiosas para detectar patrones conocidos en código escrito por humanos. En ciclos de iteración de agentes, las herramientas se convierten en objetivos de optimización que el agente aprende a evadir. Usa SAST como una señal entre varias, no como una puerta.
Implementa revertir-ante-fallo, no corregir-ante-fallo. Cuando una iteración introduce una regresión, descarta la iteración por completo. No le pidas al agente que corrija la regresión en una iteración subsecuente. El intento de corrección es en sí mismo una iteración sujeta a las mismas dinámicas de degradación. Una implementación mínima usando git:
#!/bin/bash
# monotonicity-gate.sh — revert on security regression
BASELINE_HASH="$1" # git hash of the known-good baseline
# Run your security checks against current state
CURRENT_VULNS=$(semgrep --config auto --json . | jq '.results | length')
BASELINE_VULNS=$(git stash && git checkout "$BASELINE_HASH" -q && \
semgrep --config auto --json . | jq '.results | length' && \
git checkout - -q && git stash pop -q)
if [ "$CURRENT_VULNS" -gt "$BASELINE_VULNS" ]; then
echo "Security regression: $BASELINE_VULNS → $CURRENT_VULNS vulnerabilities"
git checkout "$BASELINE_HASH" -- .
exit 2 # Block the iteration
fi
El patrón compara contra la línea base original, no contra la iteración anterior. La deriva acumulativa es la amenaza.
FAQ
¿El refinamiento iterativo siempre degrada la seguridad?
No todas las cadenas de iteración se degradan. El estudio de SCAFFOLD-CEGIS encontró que el 43,7 por ciento de las cadenas contenían más vulnerabilidades después de diez rondas, lo que significa que el 56,3 por ciento mantuvo o mejoró la postura de seguridad.1 Un estudio independiente de IEEE-ISTAS encontró un aumento del 37,6 por ciento en vulnerabilidades críticas después de cinco iteraciones.4 La preocupación es que la degradación es silenciosa: el agente produce código funcionalmente correcto que pasa las pruebas mientras las propiedades de seguridad se erosionan. Sin verificaciones explícitas de monotonicidad de seguridad, la degradación pasa desapercibida hasta que una vulnerabilidad es explotada.
¿Por qué las puertas SAST empeoran el problema en lugar de mejorarlo?
Las herramientas de análisis estático verifican patrones de vulnerabilidad conocidos. Cuando un agente recibe retroalimentación SAST entre iteraciones, optimiza para pasar el escáner en lugar de escribir código seguro. El agente evita los patrones señalados mientras introduce debilidades novedosas que el escáner no puede detectar. También elimina capas de defensa en profundidad que el escáner marca como redundantes. El efecto neto es código que pasa los escaneos pero contiene más vulnerabilidades latentes que el código producido sin puertas SAST.
¿Qué es la monotonicidad de seguridad y cómo la impone SCAFFOLD-CEGIS?
La monotonicidad de seguridad significa que ninguna iteración puede hacer el código menos seguro que la iteración anterior. SCAFFOLD-CEGIS impone esta propiedad a través de cuatro capas de verificación secuenciales: corrección (suite de pruebas), monotonicidad de seguridad (comparación SAST entre iteraciones), presupuesto de diff (limitando la escala de cambios) e integridad de ancla (verificando que los elementos de código críticos para seguridad sobrevivan). El framework usa el principio CEGIS (counterexample-guided inductive synthesis), representando los contraejemplos como reportes de fallo estructurados en lugar de pruebas formales. Si cualquier capa rechaza una iteración, el sistema la descarta por completo en lugar de pasarla al agente para su corrección. La compensación: una tasa de completitud de tareas del 77 por ciento, menor que enfoques menos estrictos.
¿En qué se diferencia revertir-ante-fallo de corregir-ante-fallo en ciclos de agentes?
Corregir-ante-fallo detecta un problema y le pide al agente que lo corrija en la siguiente iteración. El intento de corrección está sujeto a la misma deriva de especificación que causó la regresión original, y a menudo introduce nuevos problemas. Revertir-ante-fallo descarta la iteración completa y regresa al último estado conocido como válido. El agente comienza de nuevo con una línea base limpia en lugar de acumular parches correctivos. La gestión de ramas de git hace que la reversión sea trivial en la práctica.
¿Puedo aplicar estos hallazgos a mi flujo de trabajo existente con Claude Code o Codex?
Sí. Las tres acciones de la sección para profesionales aplican a cualquier ciclo de agente que modifique código a lo largo de múltiples rondas. Audita tus ciclos de iteración comparando la postura de seguridad contra la línea base original (no solo contra la iteración anterior). Trata la salida de SAST como una señal entre varias en lugar de como una puerta. Cuando una iteración introduce una regresión, usa git checkout o git revert para descartar el cambio por completo en lugar de pedirle al agente que lo corrija. El patrón de harness basado en hooks proporciona un modelo de implementación concreto para codificar estas verificaciones como puertas automatizadas.
Fuentes
-
Yi Chen et al., “SCAFFOLD-CEGIS: Preventing Latent Security Degradation in LLM-Driven Iterative Code Refinement,” arXiv:2603.08520, March 2026, arxiv.org/abs/2603.08520v1. Tested GPT-5-Nano, Claude Sonnet 4.5, DeepSeek-V3 across 24 tasks, 288 chains, 2,880 steps. 43.7% degradation rate (GPT-4o observational study); SAST gates increased SSDR from 12.5% to 20.8%; SCAFFOLD-CEGIS achieved 2.1% SSDR with 100% safety monotonicity at 77.14% task completion. ↩↩↩↩↩↩↩↩↩
-
Blake Crosley, “Anatomy of a Claw: 84 Hooks as an Orchestration Layer,” blakecrosley.com, February 2026. ↩
-
Andrej Karpathy, autoresearch: AI agents running autonomous ML research, March 2026, github.com/karpathy/autoresearch. 630-line Python script, ~700 experiments over two days, ~20 genuine improvements. ↩
-
Shivani Shukla, Himanshu Joshi, Romilla Syed, “Security Degradation in Iterative AI Code Generation: A Systematic Analysis of the Paradox,” IEEE-ISTAS 2025, arXiv:2506.11022, arxiv.org/abs/2506.11022. 10 security-verified C/Java samples, 4 prompting strategies, 10 iterations each (400 total), 37.6% increase in critical vulnerabilities after 5 iterations. 12 vulnerability categories. ↩↩