
Un sistema de auditoría de seguridad contextual para artefactos de investigación
SAFE realiza una evaluación de seguridad controlada y consciente del repositorio de los hallazgos de Semgrep y Trivy en artefactos de investigación.
Admite dos tareas de clasificación independientes: predicción directa binaria (SECURITY_RELEVANT o NON_SECURITY) y la taxonomía contextual detallada multiclase (tres etiquetas — ver Tres etiquetas). Cada tarea puede ejecutarse en modo zero-shot o agéntico.
Solo espera:
artifact_id.artifact_id.No se entrena ni se ajusta con ningún dato de evaluación etiquetado. Los datos etiquetados se usan solo después de la inferencia, para evaluar predicciones, y nunca los ve el clasificador. SAFE nunca ejecuta código de artefactos; el texto del repositorio se trata como evidencia no confiable, no como instrucciones.
Esta versión contiene el código fuente completo de safe_audit, la CLI y las pruebas, además de un autocontenido con tres artefactos de ejemplo totalmente sintéticos que puedes ejecutar de principio a fin sin ningún dato externo. Excluye el corpus real de artefactos de investigación, las etiquetas de verdad fundamental y los hallazgos de evaluación utilizados en el artículo.
Inicio rápido: después de la Instalación, ejecuta la Demo — funciona de inmediato sin configuración de datos. config.example.yaml, cubierto más adelante en Configuración, es una plantilla para tus propios hallazgos/artefactos y no se ejecutará hasta que lo edites.
cd path/to/safe-artifact-auditor
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
Establece la clave API:
export OPENAI_API_KEY="your-key"
Para un proxy LiteLLM de la organización, usa config.litellm.example.yaml en su lugar — está comentado en línea. Las credenciales y los valores de encabezados personalizados se leen de variables de entorno y nunca se almacenan en la configuración de SAFE ni en archivos de resultados.
demo/ contiene tres artefactos de ejemplo pequeños y totalmente sintéticos — ninguno derivado de ni correspondiente a ningún artefacto de investigación publicado real — uno por etiqueta de taxonomía, para que los revisores puedan ejercitar el pipeline completo sin ningún dato externo:
demo-contextual-risk/ — un agregador de checkpoints de aprendizaje federado de juguete que deserializa un checkpoint descargado de una URL proporcionada por el llamador con torch.load. Entrada no confiable y proveniente de la red alcanza un sumidero de deserialización inseguro, que se espera que SAFE clasifique como CONTEXTUAL_RISK.demo-hardening-recommendation/ — un harness de benchmark de juguete que ejecuta subprocess.run(..., shell=True) contra líneas de comando que son todas literales de Python codificadas, sin entrada controlada por el llamador. Se espera que SAFE clasifique esto como HARDENING_RECOMMENDATION: el patrón de shell es real y vale la pena señalarlo, pero nada externo puede alcanzarlo o influenciarlo.demo-false-positive/ — un generador de fixtures de prueba fijado a una versión anterior de Pillow con un aviso hipotético de bomba de descompresión. El código solo crea nuevas imágenes en memoria y nunca abre datos externos, por lo que la ruta de código real del aviso nunca se alcanza. Se espera que SAFE clasifique esto como FALSE_POSITIVE.demo/findings.csv contiene un hallazgo por artefacto, y demo/demo-zero-shot.yaml / demo/demo-agentic.yaml son configuraciones listas para ejecutar (artifact_root: . se resuelve relativo al archivo de configuración, así que ejecuta desde dentro de demo/):
cd demo
safe-audit run --config demo-zero-shot.yaml
safe-audit run --config demo-agentic.yaml
Los resultados se guardan en demo/runs/demo-zero-shot/ y demo/runs/demo-agentic/ respectivamente (ver Salida).
CONTEXTUAL_RISKHARDENING_RECOMMENDATIONFALSE_POSITIVENo se usa ninguna categoría adicional ni ninguna regla determinista de cambio de etiqueta. Un mecanismo de investigación/seguridad documentado y aislado en el código propio del artefacto se clasifica como HARDENING_RECOMMENDATION, ya que la práctica subyacente sigue siendo real incluso cuando el aislamiento limita la explotabilidad realista.
SECURITY_RELEVANT: un riesgo contextual válido o una preocupación de endurecimiento, incluido el comportamiento intencional y aislado de investigación de seguridad.NON_SECURITY: un hallazgo falso, no coincidente, no aplicable, ausente o de característica afectada demostrablemente no utilizada.El evaluador también deriva una vista binaria de las predicciones multiclase: FALSE_POSITIVE se convierte en NON_SECURITY; cualquier otra etiqueta multiclase se convierte en SECURITY_RELEVANT. Los resultados binarios directos y derivados permanecen explícitamente separados.
project/
├── config.yaml
├── data/
│ └── findings.csv
└── artifacts/
├── artifact_001/
├── artifact_002/
└── artifact_003/
El mapeo es exacto: artifact_id = artifact_001 se resuelve a artifacts/artifact_001/.
Columnas CSV requeridas:
artifact_id;tool;finding_id
Columnas opcionales:
artifact_id;tool;finding_id;category;severity_raw;file;line;message;package;version;cwe;cvss;scanner_applicable
Una columna de índice inicial sin nombre se ignora. Las columnas adicionales se conservan mediante el modelo de entrada.
Ejemplo:
artifact_id;tool;finding_id;category;severity_raw;file;line;message;package;version;cwe;cvss;scanner_applicable
artifact_001;semgrep;python.lang.security.audit.subprocess-shell-true;code;HIGH;src/probe.py;42;Shell command uses shell=True;;;;CWE-78;;yes
artifact_002;trivy;DEMO-CVE-0001;dependency;HIGH;;;Affected package (illustrative, not a real CVE);example-lib;1.2.0;CWE-502;8.1;yes
scripts/run_scanners.py y scripts/build_findings_csv.py producen el findings.csv y la disposición de artefactos descrita anteriormente directamente desde tu propio código, usando Semgrep y Trivy.
Instala Semgrep (funciona igual en cualquier sistema operativo, incluido Linux):
pip install semgrep
Instala Trivy en Linux — ya sea el repositorio apt (Debian/Ubuntu):
sudo apt-get install wget gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy
o el script de instalación oficial, que funciona en cualquier distribución de Linux e instala una versión binaria en /usr/local/bin (no se requieren paquetes raíz más allá de sudo para ese directorio):
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
Verifica que ambos estén en PATH antes de continuar:
semgrep --version
trivy --version
Luego organiza un directorio por artefacto bajo un artifact_root/ y ejecuta:
python scripts/run_scanners.py artifact_root --output scan-output
python scripts/build_findings_csv.py scan-output --output data/findings.csv
El primer comando ejecuta Semgrep y Trivy (escaneo de vulnerabilidades y secretos) contra cada directorio de artefacto y guarda el JSON sin procesar de los escáneres. El segundo analiza ese JSON en un findings.csv compatible con SAFE (las columnas coinciden con Estructura de entrada; file se informa relativo a cada directorio de artefacto). Pasa --skip-semgrep/--skip-trivy a cualquiera de los scripts para ejecutar solo una herramienta. --config en run_scanners.py fija un conjunto de reglas de Semgrep específico en lugar del auto predeterminado, que es conveniente pero no está fijado de manera reproducible.
Esta sección es para ejecutar SAFE contra tu propio CSV de hallazgos y carpetas de artefactos (ver Estructura de entrada anterior). Si solo quieres ver SAFE en acción, usa la Demo en su lugar — config.example.yaml a continuación es una plantilla y no se ejecutará tal cual.
Copia config.example.yaml:
cp config.example.yaml config.yaml
Luego edita input_csv y artifact_root (y opcionalmente paper_root) para que apunten a tus propios datos antes de ejecutar.
Configuraciones clave:
model / provider: identificador exacto del modelo OpenAI (o alias LiteLLM), y openai o litellm con URL del proxy y nombre de la variable de entorno de credenciales.analysis_mode: zero_shot o agentic.classification_task: binary o multiclass; independiente de analysis_mode.max_agent_steps: requerido solo en una configuración agéntica.max_workers / max_output_tokens / max_schema_retries: concurrencia, límite de salida por respuesta y presupuesto de reintentos de llamadas al modelo para respuestas con esquema inválido.resume / resume_policy: incomplete reintenta fallos, artefactos faltantes y hallazgos no intentados; failed_only reintenta solo fallos conservando los éxitos registrados.cost: contabilidad de costos en vivo opcional y terminación por max_run_cost_usd.El modelo predeterminado es gpt-5.6-sol. Cámbialo explícitamente si la disponibilidad, el costo o los requisitos de latencia difieren.
safe-audit run --config config.yaml
O sin instalar el comando de consola:
PYTHONPATH=src python -m safe_audit.cli run --config config.yaml
Para una comparación ejecutable y coincidente contra los datos sintéticos incluidos, ver Demo (demo/demo-zero-shot.yaml y demo/demo-agentic.yaml). Difieren solo en analysis_mode y run_name. Zero-shot realiza una llamada al modelo sobre la evidencia base. El modo agéntico comienza desde la misma evidencia y puede llamar a herramientas de repositorio de solo lectura acotadas antes de devolver el mismo resultado estructurado.
runs/<run_name>/
├── config.resolved.yaml
├── run_metadata.json
├── summary.json
├── results.jsonl
├── results.csv
├── profiles/
├── evidence/
├── raw/<finding_uid>/
│ ├── 0001-request.json
│ ├── 0001-response.json (o 0001-error.json)
│ └── final-output.txt
└── logs/
├── events.jsonl
├── result_attempts.jsonl
└── run_sessions.jsonl
results.csv está pensado para el análisis. results.jsonl conserva los registros estructurados completos. La evidencia y las salidas sin procesar del modelo respaldan la auditoría y el análisis de errores. Ambos son canónicos: contienen solo el registro más reciente de cada hallazgo, mientras que logs/result_attempts.jsonl es de solo anexión y conserva cada resultado histórico.
Al reanudar, SAFE primero vuelve a analizar las respuestas sin procesar guardadas de cada hallazgo fallido con el analizador estricto actual; una clasificación válida única se recupera sin una llamada API. Solo los fallos irrecuperables se programan para inferencia del modelo. Para una continuación solo de fallos de una ejecución parcialmente completada, mantén el mismo output_root y run_name y establece:
resume: true
resume_policy: failed_only
Para evaluar predicciones contra un CSV dorado etiquetado (con una columna security_label o security_class):
safe-audit evaluate --results runs/<run_name>/results.jsonl --gold GOLD.csv --output runs/<run_name>/evaluation.json
PYTHONPATH=src python -m unittest discover -s tests -v
La suite de pruebas usa un proveedor falso y, por lo tanto, no requiere una clave API.