FlawOpen

flawopen.com/Teardowns/cve-2026-77244-mcp-atlassian-http-auth-bypass

● CVE-2026-77244 · CVSS 10.0[1] · Crítica
Investigación · FlawOpen

CVE-2026-77244: acceso HTTP sin autenticación en mcp-atlassian

CVE-2026-77244 permitía que llamadas sin autenticar llegaran a los manejadores HTTP del proyecto comunitario mcp-atlassian, que podían recurrir a las credenciales Jira o Confluence configuradas en el entorno del operador. La corrección principal llegó en 0.22.0; quienes usan SSE necesitan 0.23.1 o posterior por otro fallo de transporte relacionado.[1], [4], [5], [6]

Vector CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N[1]
💡 Explicación en Lenguaje Sencillo (ELI5)

La recepción debe revisar la credencial de un visitante antes de abrir una puerta reservada al personal. En el flujo anterior, si no había credencial, la persona de recepción prestaba su llave maestra. El fallo combinaba dos controles ausentes: una petición HTTP podía llegar a las herramientas sin identidad verificada y estas podían usar las credenciales Atlassian compartidas del operador. La corrección rechaza las peticiones HTTP no autenticadas y exige habilitar expresamente ese fallback de credenciales.[1], [3]

Conceptos Clave y Términos

Transporte MCP
Canal que lleva las solicitudes de Model Context Protocol entre cliente y servidor. Este CVE afecta al transporte HTTP de mcp-atlassian; el aviso no afecta a stdio.[1], [4]
Fallback de credenciales globales
Uso de credenciales Jira o Confluence configuradas en el entorno del servidor cuando una solicitud no tiene identidad propia. En HTTP accesible remotamente, esto puede convertir una solicitud anónima en una acción como operador.[1], [4]
Límite de autenticación
Comprobación del servidor que establece la identidad antes de que una solicitud llegue a manejadores protegidos. El acceso de red, un token no vacío o confiar en un proxy no demuestran por sí solos la identidad.[1], [7]
CWE-287
Autenticación incorrecta: la aplicación no demuestra suficientemente la identidad declarada antes de conceder acceso.[1], [7]
CWE-303
El verificador de tokens implementa incorrectamente la autenticación: acepta cualquier token no vacío sin comprobar que sea válido.[1], [9]
CWE-862
La solicitud HTTP podía llegar a los manejadores de herramientas privilegiadas sin una comprobación de autorización que exigiera una identidad de usuario verificada.[1], [10]

Mapeos de marcos

Análisis de Causa Raíz

El aviso de seguridad de GitHub describe una cadena en el proyecto comunitario mcp-atlassian, no una vulnerabilidad de un producto de Atlassian. Antes de 0.22.0, el middleware HTTP podía dejar pasar una solicitud sin identidad de usuario hasta los manejadores de herramientas. Si el despliegue usaba credenciales del operador desde variables de entorno, JiraFetcher o ConfluenceFetcher podía recurrir a ellas. El aviso también documenta un verificador de tokens opacos que aceptaba cualquier cadena no vacía; eso no demuestra la identidad real del solicitante. El límite debe proteger conjuntamente la identidad y la selección de credenciales: un usuario ausente o no verificado nunca debe heredar la credencial privilegiada del operador. La corrección 0.22.0 devuelve HTTP 401 para solicitudes MCP streamable-HTTP no autenticadas e impide el fallback global en contexto HTTP salvo que se configure explícitamente ALLOW_GLOBAL_CRED_FALLBACK=true para un despliegue de un solo usuario. El comportamiento stdio no cambia. Por separado, GHSA-5j8j-256g-vvp5 describe un desajuste de rutas SSE corregido en 0.23.1; no es CVE-2026-77244. Actualiza los despliegues SSE a 0.23.1 o posterior y no supongas que el parche de la CVE en 0.22.0 también corrige ese otro aviso. El aviso no confirma explotación; este artículo no afirma que hubiera una intrusión real. El aviso de la CVE asigna CWE-287, CWE-303 y CWE-862 a los fallos de autenticación, verificación de tokens y autorización de esta cadena. El aviso acredita a crazydude123 como quien reportó la vulnerabilidad.[1], [3], [4], [5], [6], [7], [9], [10]

Flujo de Ataque Paso a Paso

Paso 1

Hay un endpoint HTTP MCP accesible

El despliegue ejecuta el servidor comunitario mcp-atlassian por HTTP y una parte sin autenticar puede alcanzar el transporte. Los despliegues solo por stdio quedan fuera de la ruta afectada por este CVE.[1]

Paso 2

La solicitud llega a una herramienta sin usuario verificado

Antes de 0.22.0, una solicitud HTTP sin identidad propia podía atravesar el middleware en lugar de rechazarse en el límite del transporte. El aviso también indica que una cadena no vacía no se verificaba de forma independiente como identidad.[1], [3]

Paso 3

La herramienta selecciona credenciales compartidas del operador

Si no hay identidad propia y el servidor tiene credenciales Jira o Confluence en su entorno, el fetcher puede usar las credenciales globales. Así, la solicitud puede ejercer los permisos de las herramientas habilitadas para el operador; el impacto depende de esos privilegios y de la configuración.[1], [3]

Paso 4

Rechaza en el transporte y falla de forma segura al elegir credenciales

La versión 0.22.0 devuelve HTTP 401 a solicitudes streamable-HTTP no autenticadas y bloquea el fallback global en contexto HTTP salvo habilitación explícita. Para SSE, instala 0.23.1 o posterior, que corrige el fallo separado de coincidencia de rutas.[1], [4], [5], [6]

Código Fuente: Vulnerable vs. Seguro

Representación condensada del flujo, no copia literal de las funciones completas. El parche upstream añade HTTP 401 en el límite de transporte y otra protección antes de devolver el fetcher global en contexto HTTP; ambas requieren la opción explícita ALLOW_GLOBAL_CRED_FALLBACK.[1], [3], [4]

IMPLEMENTACIÓN VULNERABLE
# Representación simplificada del flujo de control afectado.
async def handle_request(scope, ctx):
    user_identity = scope.get("state", {}).get("user_atlassian_auth_type")
    # La falta de identidad no se rechazaba en el límite HTTP.
    return await call_tool_handler(ctx, user_identity=user_identity)

def get_fetcher(user_identity, global_config):
    if user_identity:
        return fetcher_for_user(user_identity)
    # Como alternativa, usa las credenciales del operador configuradas en el entorno.
    return fetcher_from_config(global_config)
PARCHE SEGURO Y ROBUSTO
# Representación enfocada de las protecciones integradas en la versión 0.22.0.
async def handle_request(scope, ctx):
    user_identity = scope.get("state", {}).get("user_atlassian_auth_type")
    if is_mcp_http_post(scope) and not user_identity and not allow_global_fallback():
        return http_401("Authentication required")
    return await call_tool_handler(ctx, user_identity=user_identity)

def get_fetcher(user_identity, global_config, *, in_http_context):
    if user_identity:
        return fetcher_for_user(user_identity)
    if in_http_context and not allow_global_fallback():
        raise PermissionError("Refusing operator credentials for an unauthenticated HTTP request")
    return fetcher_from_config(global_config)

Lista de Verificación de Seguridad para Ingeniería

Fuentes