Durante décadas, las pruebas de seguridad estáticas de aplicaciones (SAST)han sido una de las formas más eficaces de que los equipos de seguridad escalen la revisión de código.
Pero cuando creamos Codex Security, tomamos una decisión de diseño deliberada: no comenzamos importando un informe de análisis estático para que el agente lo clasificara. Diseñamos el sistema para iniciar directamente con el repositorio, su arquitectura, sus límites de confianza y su comportamiento previsto, y para validar lo que encuentra antes de que una persona tenga que dedicarle tiempo.
La razón es simple: las vulnerabilidades más difíciles normalmente no son problemas de flujo de datos. Se producen cuando el código parece aplicar una verificación de seguridad, pero esta no garantiza realmente la propiedad de la que depende el sistema. En otras palabras, el desafío no consiste solo en rastrear cómo se mueven los datos a través de un programa, sino en determinar si las defensas implementadas en el código funcionan efectivamente.
SAST suele presentarse como un flujo limpio: identificar una fuente de entrada no fiable, rastrear los datos a través del programa y señalar los casos en que esos datos llegan a un destino sensible sin saneamiento. Es un modelo elegante y permite cubrir muchos errores reales.
En la práctica, SAST tiene que hacer aproximaciones para poder operar a gran escala, especialmente en bases de código reales con acceso indirecto, despacho dinámico, callbacks, reflexión y flujos de control dependientes de frameworks. Esas aproximaciones no son una crítica a SAST; reflejan la realidad de intentar razonar sobre el código sin ejecutarlo.
Pero eso, por sí solo, no es la razón por la que Codex Security no comienza con un informe SAST.
El problema más profundo es lo que ocurre después de rastrear correctamente una fuente hasta un destino sensible.
Incluso cuando el análisis estático rastrea correctamente la entrada a través de múltiples funciones y capas, aún debe responder la pregunta que realmente determina si existe una vulnerabilidad:
Toma un patrón común: el código llama a algo como sanitize_html() antes de renderizar contenido no fiable. Un analizador estático puede detectar que se ejecutó el sanitizador. Lo que normalmente no puede determinar es si ese sanitizador es realmente suficiente para el contexto de renderizado específico, el motor de plantillas, el comportamiento de codificación y las transformaciones posteriores implicadas.
Ahí es donde las cosas se complican. El problema no es solo si los datos llegan a un destino sensible, sino si las comprobaciones en el código realmente restringen el valor de la manera en que el sistema asume que lo hacen.
«Dicho de otro modo: hay una gran diferencia entre ‹el código llama a un sanitizador› y ‹el sistema es seguro›».
Aquí hay un patrón que aparece con frecuencia en sistemas reales.
Una aplicación web recibe una carga útil JSON, extrae un redirect_url, lo valida con una expresión regular (regex) de lista permitida, lo decodifica y pasa el resultado a un gestor de redirección.
Un informe clásico de origen a destino (source-to-sink) puede describir el flujo:
entrada no fiable → comprobación con regex → decodificación de URL → redirección
Pero la verdadera pregunta no es si la comprobación existe. Se trata de si esa comprobación sigue restringiendo el valor después de las transformaciones posteriores.
Si la regex se ejecuta antes de decodificar, ¿realmente restringe la URL decodificada de la manera en que el gestor de redirección la interpreta?
Responder a eso significa razonar sobre toda la cadena de transformaciones: qué permite la regex, cómo se comportan la decodificación y la normalización, cómo el análisis de URL trata los casos límite y cómo la lógica de redirección resuelve los esquemas y las autoridades.
Muchas de las vulnerabilidades importantes en la práctica se presentan así: errores en el orden de las operaciones, normalización parcial, ambigüedades de análisis y discrepancias entre la validación y la interpretación. El flujo de datos es visible. La debilidad está en cómo se propagan, o no se propagan, las restricciones a lo largo de la cadena de transformaciones.
Esto no es solo un patrón teórico. En CVE-2024-29041(se abre en una ventana nueva), Express se vio afectado por un problema de redirección abierta en el que las URL malformadas podían eludir implementaciones comunes de listas permitidas debido a cómo se codificaban y luego se interpretaban los objetivos de redirección. El flujo de datos era directo, y la pregunta más difícil, que determinaba si existía el fallo, era si la validación seguía siendo válida después de la cadena de transformaciones.
Codex Security está diseñado en torno a un objetivo sencillo: reducir el triaje sacando a la luz problemas con evidencia más sólida. En el producto, eso significa usar contexto específico del repositorio (incluido un modelo de amenazas) y validar problemas de alta relevancia en un entorno aislado antes de mostrarlos.
Cuando Codex Security encuentra un límite que parece una «validación» o un «saneamiento», no lo trata como un simple requisito. Intenta comprender lo que el código busca garantizar y luego trata de refutar esa garantía.
En la práctica, esto suele parecer una combinación de:
- Leer la ruta de código relevante con el contexto completo del repositorio, tal como lo haría un investigador de seguridad, y buscar discrepancias entre la intención y la implementación. Esto incluye los comentarios, pero el modelo no necesariamente los toma como ciertos, por lo que añadir //Halvar dice: esto no es un error sobre tu código no lo confunde, si realmente existe un error.
- Reducir el problema a la porción comprobable más pequeña (por ejemplo, la cadena de transformaciones alrededor de una sola entrada), de modo que se pueda razonar sobre ella sin que el resto del sistema interfiera. En este sentido, Codex Security extrae pequeños fragmentos de código y luego escribe microfuzzers para ellos.
- Razonar sobre las restricciones a lo largo de las transformaciones, en lugar de tratar cada comprobación de forma independiente. Cuando corresponde, esto puede incluir la formalización como un problema de satisfacibilidad. En otras palabras, se le da al modelo acceso a un entorno Python con z3-solver, y sabe usarlo cuando es necesario, tal como tendría que hacerlo un humano al resolver un problema de restricciones de entrada particularmente complicado. Esto es especialmente útil para analizar desbordamientos de enteros o errores similares en arquitecturas no estándar.
- Ejecutar hipótesis en un entorno de validación aislado cuando sea posible, para distinguir «esto podría ser un problema» de «esto es un problema». No hay mejor prueba que una PoC completa de principio a fin con el código compilado en modo de depuración.
Este es el cambio clave: en lugar de quedarse en «existe una comprobación», el sistema avanza hacia «la invariante se cumple (o no), y aquí está la evidencia». Y el modelo elige la mejor herramienta para esa tarea.
Una reacción lógica sería: ¿por qué no hacer las dos cosas? Empieza con un informe SAST y luego usa el agente para razonar más a fondo.
Hay casos en los que los hallazgos precomputados son útiles, especialmente para clases de errores conocidas y específicas. Pero para un agente diseñado para descubrir y validar vulnerabilidades en contexto, comenzar a partir de un informe SAST genera tres modos de fallo previsibles.
En primer lugar, puede fomentar un acotamiento prematuro. Una lista de hallazgos es un mapa de dónde ya buscó una herramienta. Si lo tratas como el punto de partida, puedes sesgar el sistema hacia dedicar un esfuerzo desproporcionado en las mismas regiones, usando las mismas abstracciones, y pasando por alto clases de problemas que no encajan con la visión del mundo de la herramienta.
En segundo lugar, puede introducir juicios implícitos que son difíciles de revertir. Muchos hallazgos SAST codifican suposiciones sobre saneamiento, validación o límites de confianza. Si esas suposiciones son incorrectas o simplemente incompletas, introducirlas en el ciclo de razonamiento puede cambiar el enfoque del agente de «investigar» a «confirmar o descartar», lo que no coincide con lo que esperamos del agente.
En tercer lugar, puede dificultar la evaluación del sistema de razonamiento. Si la cadena de análisis comienza con la salida de un informe SAST, se vuelve difícil separar lo que el agente descubrió mediante su propio análisis de lo que heredó de otra herramienta. Esa separación es importante si se quiere medir con precisión las capacidades del sistema, lo cual es necesario para que el sistema mejore con el tiempo.
Por eso creamos Codex Security para comenzar donde inicia la investigación de seguridad: desde el código y la intención del sistema, usando la validación para aumentar la confianza antes de involucrar a un humano.
Las herramientas SAST pueden ser excelentes para lo que fueron diseñadas: aplicar estándares de codificación segura, detectar problemas simples de origen a destino y reconocer patrones conocidos a gran escala con compromisos previsibles. Pueden ser una parte sólida de la defensa en profundidad.
Este artículo es más concreto: se centra en por qué un agente diseñado para razonar sobre el comportamiento y validar hallazgos no debería iniciar su trabajo a partir de una lista estática.
También vale la pena señalar una limitación relacionada del enfoque puro de origen a destino: no todas las vulnerabilidades son problemas de flujo de datos. Muchos fallos reales son problemas de estado e invariantes: omisiones en flujos de trabajo, brechas de autorización y errores de «el sistema está en un estado incorrecto». Para este tipo de errores, un valor contaminado no llega a un único «destino peligroso». El riesgo está en lo que el programa asume que siempre será cierto.
Esperamos que el ecosistema de herramientas de seguridad siga mejorando: el análisis estático, el fuzzing (pruebas de vulnerabilidad), los mecanismos de protección en tiempo de ejecución y los flujos de trabajo con agentes jugarán un papel importante.
Lo que queremos que Codex Security haga bien es la parte que más cuesta a los equipos de seguridad: convertir «esto parece sospechoso» en «esto es real, así es como falla y aquí tienes una corrección que coincide con la intención del sistema».
Si quieres obtener más información sobre cómo Codex analiza repositorios, valida los hallazgos y propone correcciones, consulta nuestra documentación(se abre en una ventana nueva).


