Frameworks y librerías escaneados
Probamos la cobertura mediante fixtures en estos frameworks. Se añaden nuevos patrones en cada release de reglas integradas.
Principales clases CWE detectadas
Estas clases CWE aparecen con mayor frecuencia en bases de código modernas de este lenguaje. StaticCodeAudit incluye reglas dedicadas para cada una, mapeadas a OWASP Top 10 / ISO 27001 / ASVS cuando es pertinente.
CWE-89
Inyección SQL
Concatenación o f-strings usados para construir queries SQL — típico con cursor.execute(f"SELECT ... {user_input}"), Django .raw() con concat, o SQLAlchemy .text() sin parámetros bind.
Detectado por la regla SCA: sql_injection_fstring
CWE-78
Inyección de comando OS
subprocess.run(shell=True, ...), os.system() con entrada de usuario. El flag shell=True permite abuso de metacaracteres shell.
Detectado por la regla SCA: os_system_injection
CWE-502
Deserialización insegura
pickle.loads(), yaml.load() sin SafeLoader, shelve, o marshal sobre bytes no confiables. Equivale a ejecución remota de código.
Detectado por la regla SCA: unsafe_deserialization
CWE-918
SSRF
requests.get(user_url), urllib.request.urlopen() sobre URLs controladas por usuario sin allow-list de esquema/host. Permite alcanzar servicios internos (endpoints metadata, RDS, etc.).
Detectado por la regla SCA: taint_ssrf
CWE-798
Credenciales hardcoded
API keys, secretos JWT, contraseñas de BD en archivos fuente. Detectados por entropía + patrones conocidos (AWS, Stripe, GitHub, Slack, etc.).
Detectado por la regla SCA: hardcoded_secret
CWE-94
Inyección de código vía compilación dinámica
Llamadas a los built-ins de compilación dinámica de Python sobre datos parcialmente controlados por el usuario.
Detectado por la regla SCA: dangerous_eval
Vulnerable vs. seguro — tres ejemplos rápidos
CWE-89
Detectado por la regla SCA: sql_injection_fstring
# Vulnerable — Flask + SQLAlchemy raw
@app.route('/user/<name>')
def user(name):
sql = f"SELECT * FROM users WHERE name = '{name}'"
return db.engine.execute(sql).fetchone()
# Seguro — parámetro bind
@app.route('/user/<name>')
def user(name):
sql = text("SELECT * FROM users WHERE name = :name")
return db.engine.execute(sql, {"name": name}).fetchone()
CWE-78
Detectado por la regla SCA: os_system_injection
# Vulnerable — shell=True con entrada de usuario
import subprocess
def ping(host):
return subprocess.run(f"ping -c 1 {host}", shell=True)
# Seguro — lista de argumentos, sin shell
import subprocess
def ping(host):
return subprocess.run(["ping", "-c", "1", host], check=False)
CWE-502
Detectado por la regla SCA: unsafe_deserialization
# Vulnerable — yaml.load sin SafeLoader
import yaml
def load_config(blob):
return yaml.load(blob) # Loader completo = RCE
# Seguro — yaml.safe_load
import yaml
def load_config(blob):
return yaml.safe_load(blob)
Qué detecta StaticCodeAudit (este lenguaje)
- Inyección SQL en SQL crudo, f-strings,
.format(), Django.raw(), SQLAlchemy.text()sin parámetros bind - Inyección de comando OS (
subprocessconshell=True,os.system,os.popen) - Deserialización insegura (
pickle,yaml.load,marshal,shelve) - SSRF vía
requests,urllib,aiohttpcon URLs controladas por usuario - Secretos hardcoded (AWS, Stripe, GitHub PAT, tokens Slack, secretos JWT, contraseñas BD, claves PEM)
- XXE y billion-laughs XML (
xml.etree,lxmlsin resolver deshabilitado) - Path traversal (
os.path.joincon entrada usuario,open()sin anclaje raíz) - Cookies inseguras (flags Flask/Django
Secure/HttpOnly/SameSitefaltantes) - CSRF exento (
@csrf_exempt, Flask sinflask-wtf) - Cripto insegura (MD5/SHA1 para seguridad, modo ECB, IV hardcoded, random débil)
- Modo debug activado en producción Flask / Django
- JWT inseguro (algoritmo
none, secreto hardcoded, sin expiración) - APIs deprecadas (PyCrypto, ssl.TLSv1, estilo urllib2)
- PII en logs y mensajes de excepción
- Misconfiguraciones CI/CD (.gitlab-ci.yml, GitHub Actions: checkout no confiable, secretos en logs)
OWASP Benchmark (Python) — validación independiente
StaticCodeAudit fue medido contra OWASP Benchmark (Python), una suite de pruebas pública y reproducible de 1.230 casos de test Python — más una comprobación real sobre 3 frameworks reconstruidos a partir de CVE publicadas.
CVE Test Suite, por framework — 2 de 3 con F1 = 100%
OWASP Benchmark Python obtiene 78,8% de precisión con 96,0% de recall (1.230 casos, metodología independiente) — los bugs reales se detectan, a costa de algo de ruido. Las 3 filas anteriores provienen de un test aparte y más duro: 45 casos reconstruidos a partir de CVE reales e históricas, en 8 frameworks y 5 lenguajes. Los 3 frameworks de Python son su mejor resultado en esa suite; desglose completo (incluyendo dónde otros lenguajes puntúan más bajo) en la <a href="/es/language-benchmarks.php" class="text-primary font-semibold hover:underline">página de benchmarks por lenguaje</a>.
Las vulnerabilidades reales rara vez caben en un solo archivo
Las aplicaciones Flask y Django dividen la lógica en capas: una vista recibe la solicitud, una función de acceso a datos construye la consulta. Un escáner limitado a un solo archivo a la vez nunca conecta ambos — ve el dato del usuario en views.py y la llamada a base de datos en db.py, pero nunca la conexión entre ambos. StaticCodeAudit sigue el dato a través de los archivos.
@app.route("/orders")
def find_order():
order_id = request.args.get("id")
return jsonify(get_order(order_id))
def get_order(order_id):
sql = f"SELECT * FROM orders WHERE id = {order_id}"
return db.execute(sql).fetchone()
order_id proviene de la solicitud HTTP en la vista, y llega a la consulta SQL un archivo después, sin modificar — StaticCodeAudit lo reporta en la línea exacta donde se ejecuta la consulta.
¿Cómo se compara esto con Bandit o Semgrep?
Bandit y Semgrep son las dos herramientas que aparecen primero cuando un equipo Python busca un escáner de seguridad gratuito. Ambas son legítimas, y muchos equipos ya usan una de ellas — esta es una comparación honesta, no una crítica.
Bandit
Gratuito, open sourceEscáner basado en AST creado específicamente para problemas de seguridad en Python (contraseñas hardcoded, shell=True, yaml.load inseguro). Maduro y muy usado, pero limitado a un solo archivo: sin seguimiento de taint entre archivos, y los hallazgos no se mapean a CWE/ISO 27001/ASVS por defecto.
Semgrep (Community)
Gratuito, motor open sourceMotor de coincidencia de patrones que cubre muchos lenguajes, incluido Python, con un amplio registro de reglas abiertas. El tier gratuito cubre la mayoría de reglas del día a día; el seguimiento de taint entre archivos, los informes de cumplimiento y algunas integraciones empresariales están en los planes de pago de Semgrep.
Comparativa completa StaticCodeAudit vs Semgrep →Ninguna de las dos se reemplaza al instalar StaticCodeAudit — si Bandit ya cubre lo que su equipo necesita, sigan usándolo. Lo que StaticCodeAudit añade: hallazgos ya mapeados a CWE/OWASP/ISO 27001/ASVS/NIST CSF (un hallazgo listo para un expediente de auditoría, no solo un ID de regla), seguimiento de taint entre archivos en toda su app Flask/Django por defecto, y 7 lenguajes más cubiertos por el mismo binario — sin un escáner distinto que configurar por lenguaje. Muchos equipos usan ambos.
Audite su código
Audite su código Python contra vulnerabilidades OWASP Top 10, misconfiguraciones específicas de frameworks y riesgos de dependencias — sin enviar una sola línea a la nube. Cubre Django, Flask, FastAPI, SQLAlchemy y la stdlib.
Descargar el binario demo Reservar una demo guiada