Análisis CodeQL
Lenguajes compatibles: Python, JavaScript/TypeScript, Go, Java/Kotlin, C/C++, C#, Ruby, Swift.
Recursos de la habilidad: Los archivos de referencia y plantillas se encuentran en {baseDir}/references/ y {baseDir}/workflows/.
Principios Esenciales
-
La calidad de la base de datos no es negociable. Una base de datos que se construye no es automáticamente buena: una compilación en caché no extrae nada mientras reporta éxito.
-
Las extensiones de datos capturan lo que CodeQL no detecta. Los proyectos Django, Spring y Express aún envuelven llamadas a bases de datos, análisis de solicitudes y ejecución de comandos en APIs específicas del proyecto que ningún modelo incluido cubre.
-
Las referencias explícitas a conjuntos de consultas previenen la eliminación silenciosa de consultas. Nunca pases nombres de paquetes a
codeql database analyze— cada paquete aplica filtros ocultos a través de sudefaultSuiteFileque pueden producir cero resultados. Siempre genera un archivo.qls. -
Cero hallazgos requiere investigación, no celebración. Puede significar extracción deficiente, modelos faltantes, paquetes incorrectos o filtrado del conjunto de consultas. Ejecuta
{baseDir}/scripts/check_db_quality.pydespués de la construcción, confirma que{baseDir}/scripts/verify_query_suite.pysalió con código cero para el conjunto en uso — los scripts de generación lo ejecutan, por lo que solo debes invocarlo manualmente para un conjunto reutilizado o editado — e indica en el informe que ambos pasaron. -
macOS Apple Silicon requiere soluciones para lenguajes compilados. El código de salida 137 es un error de coincidencia
arm64e/arm64, no un fallo de compilación. Prueba las herramientas arm64 de Homebrew o Rosetta antes de recurrir abuild-mode=none. -
Sigue los flujos de trabajo paso a paso. Cada fase condiciona la siguiente; saltarse la evaluación de calidad o las extensiones de datos deja el vacío invisible en los resultados.
Cada llamada a Bash es un shell nuevo
Nada se transfiere entre llamadas a Bash: ni variables, ni arreglos, ni funciones cargadas desde
build_log.sh. Cada bloque a continuación que utiliza un valor debe restablecerlo en el mismo bloque.
Los flujos de trabajo remiten aquí en lugar de repetirlo; lo que indican es el daño específico en ese
sitio, porque cada uno falla de manera diferente y silenciosa:
- una función perdida hace que
run_loggedsalga con código 127, que la escalera de construcción interpreta como un método fallido y baja hasta--build-mode=none, sin haber invocado nunca CodeQL - un arreglo perdido se expande a nada, por lo que cada
--threat-modely--model-packsque el usuario eligió se descarta mientras el informe final aún los lista como usados - un escalar perdido bajo
set -uaborta el bloque conunbound variable
Directorio de Salida
Todos los archivos generados (base de datos, registros de compilación, diagnósticos, extensiones, resultados) se almacenan en un único directorio de salida.
- Si el usuario especifica un directorio de salida en su prompt, úsalo como
OUTPUT_DIR. - Si no se especifica, utiliza por defecto
./static_analysis_codeql_1. Si ese ya existe, incrementa a_2,_3, etc.
En ambos casos, siempre crea el directorio con mkdir -p antes de escribir cualquier archivo.
Establece USER_SPECIFIED_DIR a la ruta literal del prompt del usuario antes de ejecutar esto,
o déjalo sin establecer para auto-incrementar. Nada más lo asigna.
# Resolver directorio de salida
USER_SPECIFIED_DIR="${USER_SPECIFIED_DIR:-}" # sustituye la ruta del usuario aquí, si la hay
if [ -n "$USER_SPECIFIED_DIR" ]; then
OUTPUT_DIR="$USER_SPECIFIED_DIR"
else
BASE="static_analysis_codeql"
N=1
while [ -e "${BASE}_${N}" ]; do
N=$((N + 1))
done
OUTPUT_DIR="${BASE}_${N}"
fi
mkdir -p "$OUTPUT_DIR"
El directorio de salida se resuelve una vez al inicio antes de que se ejecute cualquier flujo de trabajo. Todos los flujos de trabajo reciben $OUTPUT_DIR y almacenan sus artefactos allí:
$OUTPUT_DIR/
├── rulesets.txt # Paquetes de consultas seleccionados (registrados después del paso 3)
├── codeql.db/ # Base de datos CodeQL (directorio que contiene codeql-database.yml)
├── build.log # Registro de compilación
├── codeql-config.yml # Configuración de exclusión (lenguajes interpretados)
├── diagnostics/ # Consultas de diagnóstico y CSVs
├── extensions/ # YAMLs de extensiones de datos
├── raw/ # Salida de análisis sin filtrar
│ ├── results.sarif
│ └── run-all.qls | important-only.qls
└── results/ # Resultados finales (filtrados para important-only, copiados para run-all)
└── results.sarif
Descubrimiento de Bases de Datos
Una base de datos CodeQL se identifica por la presencia de un archivo marcador codeql-database.yml dentro de su directorio. Al buscar bases de datos existentes, siempre recopila todas las coincidencias — puede haber múltiples bases de datos de ejecuciones anteriores o para diferentes lenguajes.
Comando de descubrimiento. find_databases.sh imprime una ruta de base de datos por línea, filtrando
los archivos marcadores que una compilación fallida deja atrás. Construye el arreglo en el mismo bloque
que lo selecciona — cada llamada a Bash es un shell nuevo, por lo que un arreglo construido aquí está vacío
en la siguiente llamada, y la ejecución concluye que no hay base de datos:
# Sustitución de comando, no `done < <(...)`: una sustitución de proceso descarta el código de salida del
# script, por lo que "codeql no está en el PATH de este shell" (código 2) llegaría como una lista vacía
# y redirigiría a "construir una nueva base de datos" con tres bases de datos válidas en disco.
if ! DB_LIST=$("{baseDir}/scripts/find_databases.sh" "${OUTPUT_DIR:-.}" .); then
echo "ERROR: el descubrimiento de bases de datos falló — vea el mensaje anterior" >&2
exit 1
fi
FOUND_DBS=()
while IFS= read -r db; do
[ -n "$db" ] || continue
FOUND_DBS+=("$db")
done <<<"$DB_LIST"
echo "Se encontraron ${#FOUND_DBS[@]} base(s) de datos existente(s)"
# Los metadatos que necesita el prompt de selección, recopilados aquí en lugar de en un bloque
# propio: FOUND_DBS desaparece en la siguiente llamada a Bash, y un bucle sobre un arreglo que ya
# no existe no imprime nada y reporta éxito.
for db in "${FOUND_DBS[@]}"; do
CODEQL_LANG=$(codeql resolve database --format=json -- "$db" 2>/dev/null | jq -r '.languages[0]')
CREATED=$(grep '^creationMetadata:' -A5 "$db/codeql-database.yml" 2>/dev/null | grep 'creationTime' | awk '{print $2}')
echo "$db — lenguaje: $CODEQL_LANG, creado: $CREATED"
done
Nunca asumas que una base de datos se llama codeql.db — descúbrela por su archivo marcador.
Cuando se encuentren múltiples bases de datos: usa AskUserQuestion para permitir que el usuario seleccione qué base de datos usar, o para construir una nueva, basándose en el lenguaje y la hora de creación impresos anteriormente. AskUserQuestion acepta como máximo cuatro opciones, por lo que con más bases de datos, ofrece las tres más recientes más "Construir una nueva base de datos" y enumera el resto en el texto del prompt. Omite AskUserQuestion si el usuario indicó explícitamente qué base de datos usar o construir una nueva en su prompt.
Inicio Rápido
Para el caso común ("escanear este código en busca de vulnerabilidades"):
# Verifica que CodeQL esté instalado. Detente aquí si no lo está — cada comando posterior falla con
# un error menos informativo, y la ejecución desperdicia un ciclo de compilación antes de decir por qué.
if ! command -v codeql >/dev/null 2>&1; then
echo "ERROR: codeql no encontrado en el PATH. Instálalo con uno de:" >&2
echo " gh extension install github/gh-codeql # luego: gh codeql install-stub" >&2
echo " brew install --cask codeql" >&2
echo " https://github.com/github/codeql-action/releases (codeql-bundle)" >&2
exit 1
fi
# jq analiza `codeql resolve database --format=json` en el siguiente paso. Sin él,
# CODEQL_LANG vuelve vacío y la ejecución continúa con el lenguaje incorrecto.
if ! command -v jq >/dev/null 2>&1; then
echo "ERROR: jq no encontrado en el PATH (brew install jq / apt install jq)" >&2
exit 1
fi
# uv ejecuta tanto los scripts de guardia como ambos generadores de conjuntos de consultas.
# Verifícalo aquí en lugar de en la generación del conjunto, que ocurre después de la compilación
# — de lo contrario, una máquina sin uv pasa toda la compilación antes de fallar.
if ! command -v uv >/dev/null 2>&1; then
echo "ERROR: uv no encontrado en el PATH (https://docs.astral.sh/uv/getting-started/)" >&2
exit 1
fi
codeql --version
Luego resuelve OUTPUT_DIR usando el bloque en Directorio de Salida anterior —
respeta un directorio especificado por el usuario, lo que un simple auto-incremento no hace.
Luego ejecuta el pipeline completo: construir base de datos → crear extensiones de datos → ejecutar análisis usando los flujos de trabajo a continuación.
Racionalizaciones a Rechazar
Estos atajos conducen a hallazgos omitidos. No los aceptes:
- "security-extended es suficiente" - Es la línea base. Siempre verifica si los paquetes de Trail of Bits y Community Packs están disponibles para el lenguaje. Detectan categorías que
security-extendedomite por completo. - "security-and-quality es el conjunto más amplio" -
security-and-qualityexcluye todas las rutas de consultaexperimental/. Para el modo run-all, importa tantosecurity-and-qualitycomosecurity-experimental. La diferencia es de 1 a 52 consultas según el lenguaje. - "La base de datos se construyó, así que es buena" - Que una base de datos se construya no significa que haya extraído bien. Siempre ejecuta la evaluación de calidad y verifica los recuentos de archivos en comparación con los archivos fuente esperados.
- "No se necesitan extensiones de datos para frameworks estándar" - Incluso las aplicaciones Django/Spring tienen envoltorios personalizados que CodeQL no modela. Omitir extensiones significa perder vulnerabilidades.
- "build-mode=none está bien para lenguajes compilados" - Produce un análisis gravemente incompleto. Úsalo solo como último recurso absoluto. En macOS, prueba primero la solución de la cadena de herramientas arm64 o Rosetta.
- "La compilación falla en macOS, solo usa build-mode=none" - El código de salida 137 es causado por una discrepancia
arm64e/arm64, no por un fallo fundamental de compilación. Consulta macos-arm64e-workaround.md. - "Sin hallazgos significa que el código es seguro" - Ejecuta
check_db_quality.pyyverify_query_suite.pye informa que pasaron. Sin ellos, cero hallazgos y una base de datos que no extrajo nada son la misma salida. - "Solo ejecutaré el conjunto predeterminado" / "Solo pasaré los nombres de los paquetes directamente" - Cada paquete aplica filtros ocultos a través de su
defaultSuiteFiley puede producir cero resultados. Siempre usa una referencia explícita al conjunto. - "Pondré archivos en el directorio actual" - Todos los archivos generados deben ir en
$OUTPUT_DIR. Dispersar archivos en el directorio de trabajo hace imposible la limpieza y corre el riesgo de sobrescribir ejecuciones anteriores. - "Solo usaré la primera base de datos que encuentre" - Pueden existir múltiples bases de datos para diferentes lenguajes o de ejecuciones anteriores. Cuando se encuentre más de una, presenta todas las opciones al usuario. Solo omite el prompt cuando el usuario ya especificó qué base de datos usar.
- "El usuario dijo 'escanear', eso significa que quiere que elija una base de datos" - "Escanear" no es selección de base de datos. Si existen múltiples bases de datos y el usuario no nombró una, pregunta.
Selección de Flujo de Trabajo
Esta habilidad tiene tres flujos de trabajo. Una vez seleccionado un flujo de trabajo, ejecútalo paso a paso sin omitir fases.
Estas ejecuciones son largas. Una construcción de base de datos tiene cuatro métodos de respaldo, así que usa las herramientas de tarea para realizar un seguimiento del progreso. Decide qué pasos vale la pena rastrear según la ejecución.
| Flujo de Trabajo | Propósito |
|---|---|
| build-database | Crear base de datos CodeQL usando métodos de construcción en secuencia |
| create-data-extensions | Detectar o generar modelos de extensión de datos para APIs del proyecto |
| run-analysis | Seleccionar conjuntos de reglas, ejecutar consultas, procesar resultados |
Construcción sin supervisión
Este plugin incluye /static-analysis:codeql-build, que ejecuta los pasos de construcción de la base de datos
de principio a fin: detecta el lenguaje y la cadena de herramientas, recorre la escalera de métodos aplicando correcciones de
build-fixes.md entre escalones, y aplica el control de calidad.
/static-analysis:codeql-build {"target": "/abs/path", "lang": "cpp"}
No pregunta nada. Si todos los métodos fallan, y una base de datos que se construyó pero está por debajo del umbral
de calidad, regresan como estados — no-method-succeeded y built-below-threshold — para que tú
actúes aquí, porque si los errores restantes del extractor se limitan a código que nadie necesita
analizar es una decisión que la ejecución no puede tomar.
Úsalo cuando la construcción sea la parte larga e incierta y quieras que llegue a una conclusión. Trabaja build-database.md manualmente cuando quieras tener voz en qué método se prueba, o cuando un fallo de construcción necesite interpretación a medida que ocurre.
Lógica de Auto-Detección
Si el usuario especifica explícitamente qué hacer (por ejemplo, "construir una base de datos", "ejecutar análisis en ./my-db"), ejecuta ese flujo de trabajo directamente. NO llames a AskUserQuestion para la selección de base de datos si el prompt del usuario ya deja clara su intención — por ejemplo, "construir una nueva base de datos", "analizar la base de datos codeql en static_analysis_codeql_2", "ejecutar un escaneo completo desde cero".
Pipeline predeterminado para "test", "scan", "analyze" o similar: Descubre las bases de datos existentes usando el comando en Descubrimiento de Bases de Datos anterior, luego decide.
| Condición | Acción |
|---|---|
| No se encuentran bases de datos | Resolver nuevo $OUTPUT_DIR, ejecutar construcción → extensiones → análisis (pipeline completo) |
| Se encuentra una base de datos | Usar AskUserQuestion: ¿reutilizarla o construir nueva? |
| Se encuentran múltiples bases de datos | Usar AskUserQuestion, con un máximo de cuatro opciones — ver Descubrimiento de Bases de Datos |
| El usuario indicó explícitamente su intención | Omitir AskUserQuestion, actuar directamente según sus instrucciones |
Prompt de Selección de Base de Datos
Cuando se encuentren bases de datos existentes y el usuario no especificó explícitamente cuál usar,
preséntalas a través de AskUserQuestion bajo el encabezado "Bases de Datos CodeQL Existentes". Etiqueta cada
opción con la ruta, el lenguaje y la hora de creación recopilados anteriormente — ./static_analysis_codeql_1/codeql.db (language: python, created: 2026-02-24) — y haz que la última opción sea "Construir una nueva base de datos".
Después de la selección:
- Si el usuario elige una base de datos existente: Establece
$OUTPUT_DIRen su directorio padre (o el directorio que la contiene), establece$DB_NAMEen la ruta seleccionada, luego procede a extensiones → análisis. - Si el usuario elige "Construir nueva": Resuelve un nuevo
$OUTPUT_DIR, ejecuta construcción → extensiones → análisis.
Prompt de Decisión General
Si ni la base de datos ni el flujo de trabajo están claros a partir del prompt, ofrece los cuatro flujos de trabajo a través de `AskUserQue
...
[truncado para traducción]