Codex Review
gpt-5.5 · reasoning: xhigh
Critical
API Key hardcodeada en código fuente
api/v1/leads.py · línea 4
La clave
OPENAI_KEY = "sk-proj-xK9mZ..." está hardcodeada directamente. Si este commit llega al repo (incluso privado), la key queda expuesta en el historial de git para siempre y debe rotarse inmediatamente.OPENAI_KEY = "sk-proj-xK9mZ..." # EXPOSED
OPENAI_KEY = os.environ["OPENAI_API_KEY"]
Critical
SQL Injection — consulta sin parametrizar
api/v1/leads.py · línea 14
La query construye la cadena SQL con f-string interpolando directamente el email del usuario. Un atacante puede inyectar SQL arbitrario:
email = "'; DROP TABLE leads;--".db.execute(f"INSERT INTO leads VALUES ('{data['email']}', {score})")
db.execute("INSERT INTO leads VALUES (?, ?)", (data["email"], score))
Critical
Prompt Injection — datos de usuario sin sanear
api/v1/leads.py · línea 8
El objeto
data completo se interpola en el prompt sin ninguna sanitización. Un actor malicioso puede inyectar instrucciones para alterar el comportamiento del modelo o exfiltrar datos del sistema.prompt = f"Score this lead: {data}" # ANY user input!
prompt = f"Score lead: name={data.get('name','')!r} email={data.get('email','')!r}"
High
Sin validación ni schema de entrada
api/v1/leads.py · línea 7
data: dict acepta cualquier payload arbitrario. No hay Pydantic model, no se valida que email exista ni tenga formato válido. int(resp...content) lanzará ValueError si el modelo devuelve texto.
Medium
Sin autenticación en el endpoint
api/v1/leads.py · línea 6
El decorador
@router.post("/qualify") no tiene ningún middleware de autenticación (Depends(get_current_user)). Cualquiera puede invocar el endpoint y generar costes en OpenAI.
Low
Tests no cubren casos adversariales
tests/test_leads.py
Los 34 tests nuevos solo cubren el happy path. No hay tests con emails maliciosos, payloads de inyección SQL ni inputs que causen ValueError en el cast a int.
Gemini Review
gemini-3.1-pro-preview · --yolo
Critical
Secreto expuesto: OpenAI API Key en VCS
api/v1/leads.py · línea 4
La API key de OpenAI está incluida directamente en el diff. Rotar la key antes de este merge. Añadir
.env al .gitignore, usar python-dotenv y configurar git-secrets o pre-commit hooks para prevenir futuros leaks.OPENAI_KEY = "sk-proj-xK9mZ..."
import os
from dotenv import load_dotenv
load_dotenv()
OPENAI_KEY = os.getenv("OPENAI_API_KEY")
Critical
Inyección SQL — string interpolation
api/v1/leads.py · línea 14
Vulnerabilidad SQL Injection clásica. Gemini detecta que el campo
email viene directamente del body HTTP sin ningún escape. Usar siempre consultas parametrizadas o un ORM como SQLAlchemy.db.execute(f"INSERT INTO leads VALUES ('{data['email']}', {score})")
Critical
LLM Prompt Injection — inputs sin delimitar
api/v1/leads.py · línea 8
Gemini señala que interpolando el dict completo
{data} en el prompt se expone el sistema a ataques de prompt injection. Los campos deben estructurarse explícitamente y el contenido textual debe delimitarse con XML tags para aislar el input del usuario.prompt = (
"Score this lead on a 0-100 scale.\n"
"<lead>\n"
f" name: {data.get('name','unknown')}\n"
f" email: {data.get('email','unknown')}\n"
"</lead>\n"
"Reply with only a number."
)
High
Rate limiting ausente — riesgo de DoS económico
api/v1/leads.py
Sin rate limiting, cualquier actor puede lanzar miles de peticiones simultáneas que generan llamadas a la OpenAI API, acumulando un coste ilimitado. Añadir
slowapi o un API gateway con throttling por IP/usuario.
Medium
Respuesta LLM no sanitizada → ValueError no manejado
api/v1/leads.py · línea 13
int(resp.choices[0].message.content) lanza ValueError sin try/except si el modelo devuelve cualquier texto que no sea un número. La función debería retornar un score por defecto o un error 422 controlado.
Medium
Sin logging de auditoría para leads qualificados
api/v1/leads.py
No se registra quién hizo la petición, desde qué IP, con qué payload ni cuál fue el score asignado. Necesario para auditoría, debugging y detección de abuso.
Info
Dependencias: openai y pydantic versiones sin pin
requirements.txt
Las nuevas dependencias en
requirements.txt se añaden sin fijar versión exacta (openai>=1.0 en lugar de openai==1.35.3). Usar pip-compile o uv lock para reproducibilidad.🤝 Consenso entre modelos
Acuerdo total (ambos detectaron)
- API Key hardcodeada en el código
- SQL Injection sin consultas parametrizadas
- Prompt Injection con datos de usuario
- Falta validación del input (tipo, campos requeridos)
Hallazgos únicos (complementarios)
- Codex: Tests sin cobertura adversarial
- Codex: Endpoint sin autenticación
- Gemini: Rate limiting / DoS económico
- Gemini: Sin logging de auditoría
- Gemini: Dependencias sin versión fijada
🚫
MERGE BLOQUEADO — 3 issues críticos
Ambos modelos de IA revisaron el diff de forma independiente y coinciden: este PR no debe mergearse hasta que se resuelvan los 3 hallazgos críticos. La API key ya debe considerarse comprometida y debe rotarse ahora.
1. Rotar & mover API key a .env
2. Queries parametrizadas (SQL)
3. Sanitizar prompt LLM