Gestion de Baselines¶
Guia completa para gestionar baselines de hallazgos aceptados.
Tabla de Contenidos¶
- Que es un Baseline
- Crear un Baseline
- Usar un Baseline
- Ver Contenido del Baseline
- Combinar Baselines
- Mantener el Baseline
- Estrategias de Gestion
- API Programatica
Que es un Baseline¶
Un baseline es un archivo que contiene hallazgos que han sido revisados y aceptados. Estos hallazgos se excluyen de futuros escaneos.
Casos de Uso¶
| Caso | Descripcion |
|---|---|
| Falsos positivos | Hallazgos incorrectos que no son vulnerabilidades |
| Riesgo aceptado | Vulnerabilidades conocidas con riesgo aceptado |
| Pendientes | Issues que se arreglaran en el futuro |
| Legacy | Codigo heredado que no se puede modificar |
| Excepciones | Casos especiales documentados |
Estructura del Baseline¶
{
"version": "1.0",
"created_at": "2026-01-23T10:00:00Z",
"updated_at": "2026-01-23T10:00:00Z",
"entries": [
{
"rule_id": "MCP-E001",
"location_hash": "sha256:abc123...",
"file": "src/config.py",
"line": 47,
"reason": "Development API key, not used in production",
"accepted_by": "security@example.com",
"timestamp": "2026-01-23T10:00:00Z"
}
]
}
Campos de una Entrada¶
| Campo | Tipo | Descripcion |
|---|---|---|
rule_id |
string | ID de la regla |
location_hash |
string | Hash de archivo + linea |
file |
string | Ruta del archivo |
line |
int | Numero de linea |
reason |
string | Razon de aceptacion |
accepted_by |
string | Quien acepto |
timestamp |
string | Cuando se acepto |
Crear un Baseline¶
Metodo 1: Desde Resultados de Escaneo¶
# 1. Ejecutar escaneo y guardar resultados
mcp-scan scan . --output json > scan-results.json
# 2. Revisar resultados
cat scan-results.json | jq '.findings[] | "\(.rule_id): \(.title) @ \(.location.file):\(.location.line)"'
# 3. Generar baseline
mcp-scan baseline generate --from scan-results.json
# 4. El archivo baseline.json se crea
Metodo 2: Con Metadatos¶
mcp-scan baseline generate \
--from scan-results.json \
--output mi-baseline.json \
--reason "Revision inicial de seguridad" \
--accepted-by "security-team@example.com"
Metodo 3: Baseline Selectivo¶
Despues de generar, editar manualmente para incluir solo algunos hallazgos:
# Generar baseline completo
mcp-scan baseline generate --from scan-results.json
# Editar para dejar solo los aceptados
nano baseline.json
Opciones de Generacion¶
| Opcion | Alias | Default | Descripcion |
|---|---|---|---|
--from |
-f |
- | Archivo JSON de resultados |
--output |
-o |
baseline.json |
Archivo de salida |
--reason |
-r |
"" |
Razon para todas las entradas |
--accepted-by |
-a |
"" |
Quien acepta |
Usar un Baseline¶
En Escaneos¶
# Escaneo normal con baseline
mcp-scan scan . --baseline baseline.json
# Los hallazgos en baseline se filtran
Salida con Baseline¶
MCP-Scan v2.0.0
================================================================================
FINDINGS (excluding baselined)
================================================================================
HIGH: 1
- MCP-C002: Unvalidated URL in request (NEW)
File: src/api.py
Line: 18
================================================================================
Total: 1 new finding (1 high)
Baselined: 3 findings filtered
Exit code: 1
En CI/CD¶
# .github/workflows/security.yml
- name: Security Scan
run: |
mcp-scan scan . \
--baseline baseline.json \
--fail-on high \
--output sarif > results.sarif
Verificar Baseline Aplicado¶
# Ver cuantos hallazgos fueron filtrados
mcp-scan scan . --baseline baseline.json --output json | jq '.summary.baselined'
Ver Contenido del Baseline¶
Comando show¶
Salida de Ejemplo¶
BASELINE: baseline.json
=======================
Version: 1.0
Created: 2026-01-23T10:00:00Z
Updated: 2026-01-23T15:30:00Z
Total Entries: 5
BY RULE ID:
MCP-E001: 3 entries
- src/config.py:47 (Development API key)
- src/config.py:48 (Development DB password)
- src/legacy/old.py:12 (Legacy token)
MCP-A003: 1 entry
- scripts/admin.py:25 (Internal admin tool, not exposed)
MCP-N001: 1 entry
- . (Lockfile managed externally)
BY FILE:
src/config.py: 2 entries
src/legacy/old.py: 1 entry
scripts/admin.py: 1 entry
.: 1 entry
RECENT ENTRIES (last 5):
1. MCP-E001 @ src/config.py:47
Reason: Development API key, not used in production
Accepted by: security@example.com
Date: 2026-01-23
2. MCP-E001 @ src/config.py:48
Reason: Development DB password
Accepted by: security@example.com
Date: 2026-01-23
...
Salida JSON¶
{
"file": "baseline.json",
"version": "1.0",
"created_at": "2026-01-23T10:00:00Z",
"updated_at": "2026-01-23T15:30:00Z",
"total_entries": 5,
"stats": {
"by_rule_id": {
"MCP-E001": 3,
"MCP-A003": 1,
"MCP-N001": 1
},
"by_file": {
"src/config.py": 2,
"src/legacy/old.py": 1,
"scripts/admin.py": 1,
".": 1
}
},
"entries": [...]
}
Combinar Baselines¶
Escenario¶
Tienes multiples baselines de diferentes equipos o ramas:
Comando merge¶
mcp-scan baseline merge \
baseline-dev.json \
baseline-qa.json \
baseline-legacy.json \
--output baseline-combined.json
Comportamiento del Merge¶
- Deduplicacion: Entradas duplicadas se eliminan
- Conflictos: Se mantiene la entrada mas reciente
- Metadatos: Se combinan razones y aceptantes
Merging baselines...
baseline-dev.json: 10 entries
baseline-qa.json: 5 entries
baseline-legacy.json: 8 entries
Result:
Total entries: 18 (5 duplicates removed)
Written to: baseline-combined.json
Ejemplo de Merge¶
baseline-dev.json:
baseline-qa.json:
{
"entries": [
{"rule_id": "MCP-E001", "file": "src/config.py", "line": 47}, // Duplicado
{"rule_id": "MCP-B002", "file": "src/handlers.py", "line": 33}
]
}
baseline-combined.json (resultado):
{
"entries": [
{"rule_id": "MCP-E001", "file": "src/config.py", "line": 47},
{"rule_id": "MCP-B002", "file": "src/handlers.py", "line": 33}
]
}
Mantener el Baseline¶
Eliminar Entradas Especificas¶
Editar manualmente el archivo JSON:
# Abrir para edicion
nano baseline.json
# O con jq (eliminar entrada especifica)
jq 'del(.entries[] | select(.rule_id == "MCP-E001" and .file == "src/config.py"))' \
baseline.json > baseline-updated.json
Limpiar Entradas Obsoletas¶
Si el codigo ha cambiado, algunas entradas pueden ser obsoletas:
# Escanear y ver que entradas ya no coinciden
mcp-scan scan . --baseline baseline.json --output json | \
jq '.summary.baselined'
# Si es 0, el baseline puede necesitar limpieza
Actualizar Razones¶
# Editar manualmente
nano baseline.json
# Actualizar timestamp
jq '.updated_at = now | todate' baseline.json > baseline-updated.json
Auditar Baseline¶
# Ver estadisticas
mcp-scan baseline show baseline.json
# Exportar para revision
mcp-scan baseline show baseline.json --output json > baseline-audit.json
# Revisar entradas antiguas
jq '.entries | sort_by(.timestamp) | .[0:5]' baseline.json
Estrategias de Gestion¶
Estrategia 1: Baseline por Ambiente¶
baselines/
baseline-dev.json # Desarrollo permisivo
baseline-staging.json # Staging moderado
baseline-prod.json # Produccion estricto
# Desarrollo
mcp-scan scan . --baseline baselines/baseline-dev.json
# CI para staging
mcp-scan scan . --baseline baselines/baseline-staging.json --fail-on high
# Release a produccion
mcp-scan scan . --baseline baselines/baseline-prod.json --fail-on medium
Estrategia 2: Baseline por Tipo¶
baselines/
baseline-false-positives.json # Solo falsos positivos
baseline-accepted-risk.json # Riesgo aceptado
baseline-legacy.json # Codigo heredado
# Combinar para escaneo
mcp-scan baseline merge \
baselines/baseline-false-positives.json \
baselines/baseline-accepted-risk.json \
--output .mcp-scan-baseline.json
mcp-scan scan . --baseline .mcp-scan-baseline.json
Estrategia 3: Revision Periodica¶
# Cada trimestre, revisar baseline
mcp-scan baseline show baseline.json > baseline-review-Q1-2026.txt
# Limpiar entradas antiguas (> 6 meses)
jq --arg cutoff "2025-07-01T00:00:00Z" \
'.entries |= map(select(.timestamp > $cutoff))' \
baseline.json > baseline-cleaned.json
Estrategia 4: Aprobacion Requerida¶
Proceso de revision para agregar al baseline:
- PR con hallazgos: Scan falla con nuevos hallazgos
- Revision de seguridad: Equipo de seguridad revisa
- Aprobacion documentada: Se documenta razon
- Actualizacion de baseline: Se agrega con metadatos
# Agregar con documentacion
mcp-scan baseline generate \
--from new-findings.json \
--reason "Reviewed in JIRA-1234, accepted risk" \
--accepted-by "security-lead@example.com"
API Programatica¶
Usando la Libreria Go¶
package main
import (
"github.com/mcphub/mcp-scan/internal/baseline"
"github.com/mcphub/mcp-scan/pkg/scanner"
)
func main() {
// Cargar baseline existente
bl, err := baseline.Load("baseline.json")
if err != nil {
log.Fatal(err)
}
// Ejecutar escaneo
s := scanner.New(scanner.Config{Mode: "fast"})
result, err := s.Scan(context.Background(), "./src")
if err != nil {
log.Fatal(err)
}
// Aplicar baseline
filtered := s.ApplyBaseline(result, bl)
// Ver hallazgos no baselined
fmt.Printf("New findings: %d\n", len(filtered.Findings))
// Generar nuevo baseline
newBaseline := s.GenerateBaseline(result)
// Combinar con existente
merged := baseline.Merge(bl, newBaseline)
// Guardar
err = baseline.Save(merged, "baseline-updated.json")
}
Estadisticas del Baseline¶
// Obtener estadisticas
stats := bl.GetStats()
fmt.Printf("Total: %d\n", stats.Total)
fmt.Printf("By Rule:\n")
for rule, count := range stats.ByRuleID {
fmt.Printf(" %s: %d\n", rule, count)
}
Eliminar Entradas¶
// Eliminar por regla y ubicacion
bl.Remove("MCP-E001", "src/config.py", 47)
// Eliminar por ID de finding
bl.RemoveFinding(finding)
Verificar si Esta Baselined¶
// Verificar si un finding esta en baseline
if bl.Contains(finding) {
fmt.Println("Finding is baselined")
}
Buenas Practicas¶
1. Documentar Siempre¶
{
"rule_id": "MCP-E001",
"file": "src/config.py",
"line": 47,
"reason": "Development API key for local testing. Production uses env vars. See JIRA-1234.",
"accepted_by": "jane.doe@example.com"
}
2. Revisar Periodicamente¶
- Trimestral: Revisar todas las entradas
- Mensual: Revisar entradas criticas
- Cada release: Validar que baseline sigue siendo relevante
3. Versionar Baseline¶
# Mantener baseline en control de versiones
git add baseline.json
git commit -m "Update baseline: add accepted risk for MCP-E001 in config.py"
4. Separar por Criticidad¶
{
"entries": [
{
"rule_id": "MCP-A003",
"severity_at_baseline": "critical",
"requires_review_by": "2026-04-01"
}
]
}
5. Automatizar Validacion¶
# CI: Verificar que baseline no crece sin control
- name: Check baseline size
run: |
ENTRIES=$(jq '.entries | length' baseline.json)
if [ $ENTRIES -gt 50 ]; then
echo "Baseline has too many entries ($ENTRIES). Please review."
exit 1
fi
Troubleshooting¶
Baseline No Se Aplica¶
Sintoma: Los hallazgos no se filtran.
Causas: 1. Archivo movido/renombrado 2. Linea cambiada 3. Formato de baseline incorrecto
Solucion:
# Verificar que el hash coincide
mcp-scan scan . --output json | jq '.findings[0].id'
jq '.entries[0].location_hash' baseline.json
Muchos Falsos Positivos¶
Sintoma: El baseline crece demasiado.
Soluciones: 1. Usar reglas custom para casos especificos 2. Ajustar configuracion de allowlist 3. Revisar si las reglas son apropiadas
Baseline Corrupto¶
Sintoma: Error al cargar baseline.
Solucion:
Anterior: Formatos de Salida | Siguiente: Integracion CI/CD