The PATCH /api/settings endpoint writes the entire request body to persistent settings without a field whitelist. An authenticated user can set security-critical fields that are not meant to be modifiable here — notably requireLogin. Setting requireLogin: false disables authentication for the whole application, exposing all protected routes (e.g. /api/keys, /api/providers) to unauthenticated access.
The Kiro API-key validation endpoint builds an upstream URL using a user-controlled region value. By supplying a crafted region such as kiro-canary.local:8443#, an authenticated attacker can cause 9router to send the Kiro validation request to an attacker-controlled host under the constructed codewhisperer.<region> hostname. The request forwards the submitted Kiro API key as an Authorization: Bearer header.
9router validates image URLs by resolving the host before fetching, but the later server-side fetch performs a separate DNS resolution. An attacker-controlled DNS name can resolve to a public IP during validation and then rebind to an internal Docker/private IP during the fetch. This allows the server-side image prefetch to reach internal-only HTTP services (SSRF).
9router treats local loopback requests as trusted and allows access to /v1/* without an API key. In a documented/common reverse-proxy deployment where nginx forwards public traffic to the backend via 127.0.0.1, external non-Origin requests are misclassified as local. This allows unauthenticated access to /v1 APIs such as /v1/models, and may allow abuse of configured upstream provider credentials depending on the enabled providers.
9router determines whether an incoming request originates from localhost by trusting the X-9r-Real-Ip HTTP request header. This header is intended to be produced and sanitized exclusively by the bundled custom-server.js layer from the TCP socket address. In deployment modes where requests reach Next.js directly (the header is never stripped/regenerated), a remote, unauthenticated attacker can simply send X-9r-Real-Ip: 127.0.0.1 and be treated as a local client. This bypasses the API-key requirement …
9router enforces a progressive login lockout (5 failed attempts → temporary 30s+ lock) keyed on the client IP. The client IP used for this limiter is taken from the X-9r-Real-Ip request header, which is intended to be set only by the bundled custom-server.js layer from the unspoofable TCP socket address. In deployment modes where requests reach Next.js directly, a remote attacker controls this header and can assign a unique value …
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 …
9router's request guard decides a request is "local" (and therefore exempt from API-key auth on the /v1 LLM proxy) by reading the client-controlled Host header. Because 9router binds 0.0.0.0 by default (and the CLI misleadingly prints "localhost"), a remote, unauthenticated attacker who can reach the port can send Host: localhost to be treated as local and obtain /v1 proxy access with no API key, no CLI token, and no dashboard …
A Server-Side Request Forgery (SSRF) vulnerability exists in the 9Router dashboard via the /api/auth/oidc/test endpoint. The application accepts a user-controlled URL string through the issuerUrl parameter and performs an outbound HTTP request without validating if the destination IP belongs to a restricted internal network range. Notably, this endpoint can be accessed without active session authentication (Unauthenticated), allowing any remote actor with network visibility to the dashboard API endpoints to trigger …
The /api/settings/database endpoint allows full database export (containing all credentials, API keys, OAuth tokens, and settings) and full database import (complete overwrite) without any authentication requirement beyond the ALWAYS_PROTECTED middleware check, which only validates JWT or CLI token. Combined with other vulnerabilities (e.g., default password, tunnel exposure), this enables complete database takeover.
The 9router dashboard login rate limiter derives the client identity from the attacker-controlled X-Forwarded-For HTTP header. When 9router is directly exposed, or deployed behind a reverse proxy that does not overwrite untrusted forwarding headers, a remote attacker can rotate the X-Forwarded-For value on each login attempt and receive a fresh rate-limit bucket every time. This bypasses the dashboard brute-force protection and makes the login lockout mechanism ineffective.
Multiple critical API security vulnerabilities were discovered in 9Router's Next.js dashboard. The /api/providers endpoints lack authentication entirely, allowing anyone to create, read, update, and delete provider connections. Additionally, /api/usage/stats exposes full plaintext API keys, and /api/usage/request-logs + /api/usage/request-details expose all users' request history and full conversation contents (including system prompts, user messages, assistant responses) without authentication.
9router uses a publicly known hardcoded string "9router-default-secret-change-me" as the fallback of JWT secret for all Dashboard session JWTs when the JWT_SECRET environment variable is not set. Because this secret is committed in the public repository and unchanged across all releases, any unauthenticated remote attacker can forge a valid auth_token cookie and gain full access to dashboard and api (If JWT_SECRET is not set on server) . This vulnerable affected …
POST /api/tunnel/tailscale-install accepts a JSON body with a sudoPassword field and pipes it, followed by the body of https://tailscale.com/install.sh, into a child process spawned as sudo -S sh. The route is not present in the dashboard middleware matcher in src/proxy.js, so the request reaches the handler without invoking dashboardGuard.proxy(). In deployments where the Node process runs as root (Docker images derived from node:* without a USER directive, npm i -g …
The fix for CVE-2026-46339 (unauthenticated RCE via unprotected MCP plugin routes) introduced a local-only access gate in src/dashboardGuard.js that restricts spawn-capable routes (/api/mcp/, /api/tunnel/, /api/cli-tools/*) to loopback requests. The gate determines "local" by inspecting the Host and Origin HTTP headers rather than the TCP source address. When 9router is deployed behind a reverse proxy, tunnel (Cloudflare Tunnel, Tailscale — both natively supported), or is subject to DNS rebinding, these headers …
9router exposes two unauthenticated API endpoints that, when chained together, allow any network-adjacent attacker to execute arbitrary OS commands as the user running the 9router process — with zero prerequisites and no credentials required. The vulnerability exists because the Next.js middleware that enforces authentication (src/proxy.js) only guards 8 explicitly listed routes. The attack surface of /api/cli-tools/* and /api/mcp/* (40+ routes) receives no authentication whatsoever.
A security vulnerability has been detected in decolua 9router up to 0.3.47. The impacted element is an unknown function of the file /api of the component Administrative API Endpoint. The manipulation leads to authorization bypass. The attack is possible to be carried out remotely. The exploit has been disclosed publicly and may be used. Upgrading to version 0.3.75 is sufficient to resolve this issue. It is suggested to upgrade the …