Un JWT con firma válida no es automáticamente válido para toda API que confía en esa clave. El token también debe haber sido emitido por la autoridad esperada y para la audiencia correcta. La CVE-2026-66908 muestra qué ocurre cuando esa segunda parte desaparece silenciosamente: Apache Camel aceptaba tokens destinados a otro servicio, siempre que no hubieran expirado y estuvieran firmados por una clave presente en el keystore configurado.
Este escenario es especialmente relevante en empresas que comparten un proveedor de identidad entre varias aplicaciones. El atacante no necesita falsificar una firma ni descubrir el secreto del JWT. Necesita obtener legítimamente un token aceptado por el mismo dominio de confianza y presentarlo a una API que debería rechazar ese emisor o esa audiencia.

Qué confirma la CVE-2026-66908
Apache clasifica la falla como alta y CWE-287, autenticación impropia. El registro de NVD muestra un CVSS 3.1 de 7.5 atribuido a CISA-ADP, con vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N; NVD todavía no publicó una puntuación propia. El componente afectado es camel-platform-http-main, desde la versión 4.8.0 hasta antes de la 4.22.0. Tanto el servidor HTTP de la aplicación como el servidor de administración pasaban por la ruta vulnerable.
- Precondición: autenticación JWT habilitada con un keystore y sin jwtIssuer ni jwtAudience
- Lo que sí se validaba: firma y expiración del token
- Lo que no se validaba: las claims iss y aud
- Acceso necesario: red, sin credencial previa en la API objetivo
- Versión con comportamiento fail closed: Apache Camel 4.22.0
Dónde desaparecía la validación
Según el advisory, JWTAuthenticationConfigurer.buildJwtOptions devolvía null cuando jwtIssuer y jwtAudience no estaban configurados. El código que lo llamaba omitía JWTAuthOptions.setJWTOptions, y Vert.x JWTAuth se construía solo con el keystore. El servidor arrancaba normalmente, sin advertir que la política aplicada era más permisiva de lo esperado. Las opciones de issuer y audience llegaron a la línea principal recién en la versión 4.21.0, por lo que versiones anteriores ni siquiera ofrecían ese control en este componente.
GET /orders HTTP/1.1
Host: api-b.example
Authorization: Bearer <unexpired-token-for-api-a-signed-by-a-trusted-key>
Accept: application/jsonLa prueba decisiva no consiste en enviar un token inválido. Consiste en comparar dos tokens legítimos firmados por una clave confiable: uno con aud correspondiente a la API y otro emitido para una audiencia diferente. En la configuración vulnerable, ambos podían superar la autenticación. Esto hace que el hallazgo sea fácil de perder en pruebas que solo verifican tokens expirados, firmas modificadas y algoritmos inseguros.

La firma no reemplaza al contexto
La firma responde si el token fue modificado y si vino de una clave confiable. La claim iss identifica quién lo emitió; aud limita para qué recurso fue creado. En un proveedor multi-tenant o un keystore que confía en varias claves, omitir esas dos comparaciones amplía el conjunto de credenciales aceptadas. Incluso con un solo emisor corporativo, un token de una aplicación interna puede obtener acceso a otra API sin que el IdP haya autorizado ese uso.
- Mapea todos los emisores y claves aceptados por el keystore, no solo el IdP nominal
- Solicita tokens para dos audiencias controladas y compara la respuesta del mismo endpoint
- Repite la prueba en el servidor de la aplicación y en el servidor de administración
- Accede al backend por la ruta directa para confirmar que el gateway no sea la única capa que valida claims
- Verifica si los logs internos de autenticación distinguen token expirado, firma inválida y audiencia incorrecta
Cómo hacer el triage sin explotar producción
La primera etapa puede ser completamente estática. Confirmamos la versión resuelta en el build y buscamos las propiedades de autenticación en archivos de aplicación, manifests y charts. El comando siguiente no envía tráfico ni manipula tokens. Revela si el componente está presente y si la configuración menciona los controles relevantes. Los secretos no deben copiarse al informe.
./mvnw -q dependency:tree \
-Dincludes=org.apache.camel:camel-platform-http-main
rg -n 'authenticationEnabled|jwtKeyStore|jwtIssuer|jwtAudience|jwtAllowMissingIssuerAndAudience' \
src/main/resources deploy chartsDespués del triage, una prueba dinámica controlada debe usar tokens emitidos para el laboratorio y observar también la ruta directa hacia Camel. Si la validación de iss y aud existe solo en el API gateway, cualquier ruta interna, ingress alternativo o puerto de administración que evite el gateway reabre la falla de confianza.
La corrección exige atención a la línea de versión
La recomendación principal de Apache es actualizar a 4.22.0. En esa versión, el servidor se niega a iniciar con un keystore JWT cuando issuer y audience están ausentes, salvo que el operador habilite explícitamente jwtAllowMissingIssuerAndAudience. Este opt-out tiene false como valor predeterminado. El cambio convierte una política implícita y permisiva en una decisión visible de configuración.
- Actualiza preferentemente a Apache Camel 4.22.0 o posterior
- En la línea 4.14.x, usa al menos 4.14.9 y configura jwtIssuer, jwtAudience o ambos
- En la línea 4.18.x, usa al menos 4.18.4 y configura jwtIssuer, jwtAudience o ambos
- No trates la actualización a 4.14.9 o 4.18.4 como corrección automática, el valor predeterminado permisivo se mantuvo en esas líneas
- Mantén jwtAllowMissingIssuerAndAudience deshabilitado en 4.22.0 o posterior
- Restringe el keystore al menor conjunto posible de claves, idealmente con un signer dedicado al servicio
- Garantiza que el backend y la interfaz de administración no puedan evitar la validación realizada por el gateway
Qué cambia esto en el alcance de un pentest
Probar JWT no termina al intentar alg none o modificar la firma. Un pentest de API necesita probar la frontera entre servicios: token correcto para el usuario, pero incorrecto para el recurso; clave confiable, pero emisor inesperado; acceso negado en el gateway, pero aceptado por el backend. La CVE-2026-66908 es un buen ejemplo de una falla que supera un checklist superficial y aparece cuando la prueba sigue la identidad completa, desde la emisión hasta cada punto que toma la decisión de acceso.