FlawOpen

flawopen.com/Teardowns/cve-2026-97662-aws-security-agent-mcp-git-argument-injection

● CVE-2026-97662 · CVSS v4 6.9 · Media
Investigación · FlawOpen

CVE-2026-97662: inyección de argumentos Git en AWS Security Agent MCP

CVE-2026-97662 permitía que una referencia Git controlada por quien llama a AWS Security Agent MCP diff scan se interpretara como opción de comando, eludiendo el aislamiento del workspace y permitiendo escribir archivos en el host. Actualiza a 0.2.0 o posterior.[1], [2]

Vector CVSSCVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N
💡 Explicación en Lenguaje Sencillo (ELI5)

A un empleado le dan la etiqueta de una carpeta, pero acepta una etiqueta que empieza con una instrucción de control. El sistema de archivo sigue la instrucción en vez de buscar la carpeta. Aquí, una referencia Git que empezaba con guion podía interpretarse como opción; rechazar referencias vacías o con aspecto de opción antes de ejecutar Git cierra esa entrada. Esto es análisis de opciones de Git, no ejecución arbitraria de comandos del shell.[2]

Conceptos Clave y Términos

Servidor MCP
Proceso local que ofrece herramientas a una aplicación de IA mediante Model Context Protocol. Los argumentos de las herramientas llegan al servidor como datos no confiables.
Inyección de argumentos (CWE-88)
Un programa de línea de comandos interpreta una entrada no confiable como opción o delimitador, aunque el proceso reciba una lista de argumentos y no una cadena de shell.[2], [4]
Referencia Git
Nombre o expresión que identifica un commit o árbol, como main o HEAD~1. Un valor que empieza con - puede interpretarse como opción.[2], [3]
Aislamiento del workspace
Límite que debe mantener las operaciones de archivos de una herramienta dentro del directorio del proyecto. No se cumple si una entrada cambia el significado del comando secundario.[1], [3]

Mapeos de marcos

Análisis de Causa Raíz

AWS describe un fallo contextual de inyección de argumentos en la operación diff scan: una referencia proporcionada al escaneo podía tratarse como opción de línea de comandos en lugar de revisión Git. El PR upstream confirma que start_diff_scan pasaba base_ref a git diff <base_ref> -- y git archive; valores vacíos o que empezaban con guion podían interpretarse de forma distinta. No es inyección de metacaracteres de shell: una lista de argumentos evita el análisis del shell, pero el programa invocado aún puede interpretar una opción. AWS indica que el resultado podía crear, sobrescribir o truncar archivos fuera del workspace previsto, dentro de los permisos del proceso. La corrección integrada valida base_ref antes de Git y rechaza valores en blanco o cuyo texto recortado empieza con -; las pruebas confirman que no hay proceso ni carga para entradas rechazadas. Afecta a versiones >=0.1.1 y <0.2.0; 0.2.0 lo corrige. El registro CVE asigna CVSS 4.0 6,9 Medio; GitHub Advisory también informa CVSS 3.1 8,2 Alto. No se reproduce una carga de explotación.[1], [2], [3], [4]

Flujo de Ataque Paso a Paso

Paso 1

Un agente invoca diff scan

El servidor MCP local recibe un base_ref influido por quien llama. El riesgo depende de un flujo que permita que un repositorio, contenido o usuario no confiable influya en ese valor; una prompt injection no llega automáticamente a esta ruta.[2]

Paso 2

El valor llega a Git como argumento posicional

El código afectado pasa la referencia a comandos Git de diff y archive. Un guion inicial puede hacer que Git la trate como opción, aunque Python no use shell.[2], [3]

Paso 3

El análisis de opciones de Git rompe el límite supuesto

Una opción creada para este contexto puede dirigir escrituras fuera del workspace. El impacto documentado es crear, sobrescribir o truncar archivos que el proceso pueda escribir; el alcance depende de los permisos y del flujo.[1], [3]

Paso 4

Rechaza referencias inseguras antes de efectos secundarios

La versión 0.2.0 valida base_ref antes de Git, la carga a S3 o la comprobación del espacio del agente. Actualiza y ejecuta el proceso MCP con privilegios mínimos y aislamiento.[1], [3], [6]

Trazado del límite: texto de revisión y opciones de Git

Flujo conceptual de datos; no es una secuencia de comandos ni una reproducción del exploit.

Dos analizadores, dos límites distintos

Análisis del shell
Una lista de argumentos impide que el shell interprete el valor como sintaxis del shell y cierra ese límite.[3]
Análisis de opciones de Git
Git sigue interpretando su propia gramática de línea de comandos. La lista no impide que una referencia controlada por quien llama se interprete como opción; valídala antes de ejecutar Git.[2], [3]
1

Quien llama influye en la revisión

La herramienta diff scan recibe base_ref de un flujo de trabajo. El riesgo solo existe si una fuente no confiable puede influir en ese valor.[2], [3]

2

La lista de argumentos aún llega al analizador de Git

Python puede pasar cada valor por separado y evitar el análisis del shell, pero Git sigue interpretando sus propias opciones de línea de comandos.[3], [2]

3

Puede fallar la suposición sobre el workspace

Si Git trata el valor como una opción, la salida de archivos puede salir del workspace previsto, limitada por los permisos del sistema operativo del proceso MCP.[1], [2]

4

La validación cierra el límite de entrada

La versión 0.2.0 rechaza referencias vacías o similares a opciones antes de ejecutar Git u otros efectos secundarios. La entrada ya no puede elegir el comportamiento de las opciones de Git; las referencias válidas siguen seleccionando la revisión solicitada.[3], [6]

Código Fuente: Vulnerable vs. Seguro

Comparación enfocada en el límite de llamada upstream, no una copia completa del scanner. El cambio integrado valida la referencia antes de Git; las pruebas cubren valores vacíos y con guion inicial sin proceso ni carga. Una lista de argumentos evita el análisis del shell, pero no evita que Git interprete opciones. Este fragmento muestra solo la llamada a git diff; la misma validación debe proteger cada uso de base_ref, incluido git archive.[3]

IMPLEMENTACIÓN VULNERABLE
def start_diff_scan(path: str, base_ref: str):
    # La referencia similar a una opción llega a Git antes de validarse.
    return subprocess.run(
        ["git", "diff", base_ref, "--"],
        cwd=path,
        check=False,
    )
PARCHE SEGURO Y ROBUSTO
def _validate_git_ref(base_ref: str) -> None:
    if not base_ref or not base_ref.strip():
        raise ValueError("base_ref must not be empty.")
    if base_ref.strip().startswith("-"):
        raise ValueError("base_ref must not start with '-'.")

def start_diff_scan(path: str, base_ref: str):
    _validate_git_ref(base_ref)  # Rechace antes de iniciar subprocesos o subir archivos.
    return subprocess.run(
        ["git", "diff", base_ref, "--"],
        cwd=path,
        check=False,
    )

Lista de Verificación de Seguridad para Ingeniería

Fuentes