Skip to content

Modos de Analisis

MCP-Scan ofrece dos modos de analisis con diferentes niveles de profundidad y rendimiento.


Tabla de Contenidos

  1. Vision General
  2. Modo Fast
  3. Modo Deep
  4. Comparativa Detallada
  5. Taint Analysis
  6. Call Graph
  7. Cuando Usar Cada Modo
  8. Optimizacion del Rendimiento

Vision General

Caracteristica Fast Deep
Analisis Intra-procedural Inter-procedural
Velocidad Rapido (segundos) Lento (minutos)
Precision Media Alta
Cobertura Funcion por funcion Flujos entre funciones
Memoria Baja Alta
Uso tipico CI/CD, PRs Auditorias, certificacion
# Modo fast (por defecto)
mcp-scan scan . --mode fast

# Modo deep
mcp-scan scan . --mode deep

Modo Fast

Descripcion

El modo fast realiza analisis intra-procedural, es decir, analiza cada funcion de forma aislada sin seguir el flujo de datos entre funciones.

Como Funciona

# Ejemplo: Funcion con vulnerabilidad
@tool
def execute_command(cmd: str) -> str:
    # El modo fast detecta esto porque:
    # 1. cmd es parametro de tool (source)
    # 2. subprocess.run con shell=True es sink
    # 3. El flujo source → sink esta dentro de la misma funcion
    return subprocess.run(cmd, shell=True, capture_output=True).stdout

Detecciones en Modo Fast

El modo fast detecta:

  1. Patrones directos - Expresiones regulares sobre codigo
  2. Flujos intra-procedurales - Source a sink dentro de una funcion
  3. Configuraciones inseguras - Cookies sin Secure, JWT sin verificacion
  4. Secretos hardcodeados - Variables con valores sensibles
  5. Tool poisoning basico - Descripciones maliciosas
# DETECTADO en modo fast
@tool
def run(command: str) -> str:
    return os.system(command)  # Flujo directo

# NO DETECTADO en modo fast (requiere deep)
@tool
def run(command: str) -> str:
    safe_cmd = sanitize(command)  # Otra funcion
    return execute(safe_cmd)       # Otra funcion

Ventajas del Modo Fast

  • Velocidad: Segundos en lugar de minutos
  • Memoria: Bajo consumo de RAM
  • Paralelismo: Archivos analizados independientemente
  • Determinismo: Resultados consistentes y rapidos

Limitaciones del Modo Fast

  • No sigue flujos entre funciones
  • No detecta sanitizadores en otras funciones
  • Puede tener falsos negativos en codigo modular
  • No construye call graph

Modo Deep

Descripcion

El modo deep realiza analisis inter-procedural, construyendo un call graph y siguiendo el flujo de datos a traves de multiples funciones.

Como Funciona

# Ejemplo: Flujo entre funciones
def get_user_input() -> str:
    return input()  # Source

def process_input(data: str) -> str:
    return data.strip()  # Propagacion

def execute(cmd: str):
    os.system(cmd)  # Sink

@tool
def handler():
    data = get_user_input()  # Taint: data
    processed = process_input(data)  # Taint: processed
    execute(processed)  # DETECTADO en modo deep

Construccion del Call Graph

El modo deep construye un grafo de llamadas:

handler()
    ├── get_user_input() → [source: user_input]
    ├── process_input(data) → [taint propagation]
    └── execute(cmd) → [sink: os.system]

Detecciones Adicionales en Modo Deep

  1. Flujos inter-procedurales - Source en una funcion, sink en otra
  2. Sanitizadores en funciones separadas - Reduce falsos positivos
  3. Callbacks y closures - Variables capturadas
  4. Imports entre archivos - Flujos cross-file
# DETECTADO en modo deep
# archivo: utils.py
def execute_query(sql: str):
    cursor.execute(sql)  # Sink

# archivo: handlers.py
@tool
def search(query: str) -> str:  # Source
    result = execute_query(f"SELECT * WHERE name='{query}'")
    return result

Ventajas del Modo Deep

  • Deteccion de flujos complejos
  • Menos falsos negativos
  • Analisis de sanitizadores
  • Mejor cobertura en codigo modular

Limitaciones del Modo Deep

  • Mas lento (minutos vs segundos)
  • Mayor consumo de memoria
  • Puede timeout en proyectos grandes
  • No soporta todas las construcciones dinamicas

Comparativa Detallada

Tabla de Capacidades

Capacidad Fast Deep
Deteccion de patrones Si Si
Flujo intra-procedural Si Si
Flujo inter-procedural No Si
Call graph No Si
Analisis de sanitizadores Parcial Completo
Flujos cross-file No Si
Closures y callbacks No Si
Imports/exports No Si
Resolucion de tipos Basica Avanzada
Analisis de retornos No Si

Ejemplo Comparativo

# Codigo a analizar
def sanitize(data: str) -> str:
    return shlex.quote(data)

def execute(cmd: str):
    subprocess.run(cmd, shell=True)

@tool
def run_safe(command: str) -> str:
    safe = sanitize(command)
    execute(safe)
    return "done"

@tool
def run_unsafe(command: str) -> str:
    execute(command)
    return "done"

Resultados:

Modo run_safe run_unsafe
Fast ALERTA (falso positivo) ALERTA (correcto)
Deep OK (sanitizado) ALERTA (correcto)

El modo deep reconoce que sanitize() es un sanitizador y no reporta run_safe.


Taint Analysis

Que es Taint Analysis

Taint analysis rastrea el flujo de datos "contaminados" (tainted) desde fuentes de entrada (sources) hasta operaciones peligrosas (sinks).

Sources (Fuentes de Datos)

Source Descripcion Ejemplo
tool_input Parametros de tools MCP @tool def f(cmd: str)
env_var Variables de entorno os.environ["KEY"]
http_request Datos de request HTTP request.args
file_content Contenido de archivos open(f).read()
db_result Resultados de BD cursor.fetchone()
config Valores de configuracion config["setting"]

Sinks (Operaciones Peligrosas)

Sink Descripcion Ejemplo
exec Ejecucion de comandos os.system(), subprocess.run()
eval Evaluacion dinamica eval(), exec()
filesystem Operaciones de archivo open(), shutil.copy()
network Operaciones de red requests.get(), urllib.urlopen()
database Queries de BD cursor.execute()
logging Registro logger.info()
response Respuestas return data

Sanitizers (Funciones Seguras)

Sanitizer Proposito Ejemplo
shlex.quote Escapar shell shlex.quote(cmd)
html.escape Escapar HTML html.escape(text)
parameterized SQL parametrizado cursor.execute(sql, (param,))
os.path.basename Solo nombre de archivo os.path.basename(path)

Flujo de Taint

SOURCE ──► PROPAGACION ──► SANITIZER? ──► SINK
           (asignacion,     (rompe         (operacion
            concat,          cadena)        peligrosa)
            llamadas)

Ejemplo de flujo:

@tool
def search(query: str) -> str:  # SOURCE: query tainted
    sql = f"SELECT * FROM users WHERE name='{query}'"  # PROPAGACION: sql tainted
    cursor.execute(sql)  # SINK: tainted data llega a sink
    # ALERTA: SQL Injection

Call Graph

Que es el Call Graph

Un call graph es un grafo dirigido donde: - Nodos: Funciones/metodos - Aristas: Llamadas entre funciones

Ejemplo de Call Graph

def main():
    handler()

def handler():
    data = get_input()
    process(data)

def get_input():
    return input()

def process(x):
    execute(x)

def execute(cmd):
    os.system(cmd)

Call Graph resultante:

main
  └── handler
        ├── get_input
        └── process
              └── execute

Uso del Call Graph

El modo deep usa el call graph para:

  1. Seguir taint entre funciones
  2. Detectar sanitizadores en el camino
  3. Calcular alcanzabilidad
  4. Identificar puntos de entrada

Caching del Call Graph

El call graph se puede cachear para escaneos futuros:

# Primer escaneo (construye cache)
mcp-scan scan . --mode deep

# Escaneos siguientes (usa cache)
mcp-scan scan . --mode deep  # Mas rapido

El cache se guarda en .mcp-scan/callgraph.gob y se invalida cuando: - Los archivos cambian (hash diferente) - Se modifican dependencias


Cuando Usar Cada Modo

Usar Modo Fast

Escenario Razon
CI/CD en cada PR Velocidad critica
Pre-commit hooks Feedback inmediato
Desarrollo local Iteracion rapida
Proyectos muy grandes Evitar timeouts
Primera pasada Identificar obvios
# .github/workflows/pr.yml
- run: mcp-scan scan . --mode fast --fail-on high

Usar Modo Deep

Escenario Razon
Auditoria de seguridad Maxima cobertura
Certificacion Requerido por compliance
Release final Antes de produccion
Codigo critico Alta seguridad requerida
Investigacion de hallazgos Entender flujos
# .github/workflows/release.yml
- run: mcp-scan scan . --mode deep --output evidence

Estrategia Combinada

# En cada PR: fast
mcp-scan scan . --mode fast --fail-on critical

# Nightly: deep
mcp-scan scan . --mode deep --fail-on high

# Pre-release: deep con evidencias
mcp-scan scan . --mode deep --output evidence

Optimizacion del Rendimiento

Optimizar Modo Fast

# Limitar archivos
include:
  - "src/**/*.py"  # Solo source

exclude:
  - "**/tests/**"
  - "**/vendor/**"

# Aumentar workers
scan:
  workers: 8
  timeout: 2m

Optimizar Modo Deep

# Limitar scope
include:
  - "src/core/**/*.py"  # Solo codigo critico

# Usar cache
scan:
  mode: deep
  timeout: 30m
  workers: 4

# Excluir tests
exclude:
  - "**/tests/**"
  - "**/mocks/**"

Tips de Rendimiento

Tip Impacto
Excluir node_modules/vendor Alto
Limitar a src/ Alto
Aumentar workers Medio
Usar cache (deep) Medio
Deshabilitar LLM Medio
Deshabilitar CodeQL Alto

Benchmarks Tipicos

Proyecto Archivos Fast Deep
Pequeno (10 archivos) 10 2s 15s
Mediano (100 archivos) 100 10s 2m
Grande (1000 archivos) 1000 1m 15m
Muy grande (10000 archivos) 10000 5m 1h+

Resumen

Aspecto Fast Deep
Velocidad Segundos Minutos
Precision Media Alta
Memoria Baja Alta
Call Graph No Si
Cross-file No Si
Sanitizadores Parcial Completo
Uso CI/CD Auditorias

Recomendacion general:

  • Desarrollo diario: --mode fast
  • Antes de release: --mode deep
  • Auditoria formal: --mode deep --output evidence

Anterior: Configuracion | Siguiente: Formatos de Salida