Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-55501

CVE-2026-55501: 9Router Auth Bypass Vulnerability

CVE-2026-55501 is an authentication bypass vulnerability in 9Router that allows attackers to circumvent rate limiting and brute-force dashboard passwords. This post covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-55501 Overview

CVE-2026-55501 is a rate-limiting bypass vulnerability in 9Router, an AI router and token saver application. The dashboard login rate limiter derives the client identity from the attacker-controlled X-Forwarded-For HTTP header. Because the login endpoint uses this spoofable value as the key for checkLock and recordFail, an attacker can rotate the header on each request to obtain a fresh rate-limit bucket. This bypasses the 5-attempt threshold and progressive lockout, enabling unlimited brute-force attempts against the dashboard password. The issue is tracked under [CWE-307] Improper Restriction of Excessive Authentication Attempts and is fixed in version 0.4.80.

Critical Impact

Remote unauthenticated attackers can perform unlimited brute-force attempts against the 9Router dashboard login, defeating account lockout entirely.

Affected Products

  • 9Router versions prior to 0.4.80
  • Component: src/lib/auth/loginLimiter.js
  • Component: src/app/api/auth/login/route.js

Discovery Timeline

  • 2026-07-10 - CVE-2026-55501 published to NVD
  • 2026-07-10 - Last updated in NVD database

Technical Details for CVE-2026-55501

Vulnerability Analysis

The 9Router dashboard implements a progressive lockout mechanism that tracks failed login attempts and locks out clients after five failures. The limiter identifies clients by reading the X-Forwarded-For request header, a value typically set by upstream proxies but fully controllable by any remote HTTP client when the application is exposed directly or behind a permissive proxy chain. Because the limiter never validates the trusted proxy hop count and never falls back to the real socket peer address, attackers can generate arbitrary identity keys per request.

Each unique header value produces its own rate-limit bucket in checkLock and recordFail. Rotating the header on every attempt keeps every bucket well below the 5-attempt threshold, so the lockout never triggers. The result is unrestricted online password guessing against the administrative dashboard.

Root Cause

The root cause is trust in an attacker-controlled HTTP header as the source of client identity for a security control. loginLimiter.js uses the raw X-Forwarded-For value without validating a trusted proxy chain or preferring the TCP peer address. This design pattern violates [CWE-307] because the limiting mechanism can be trivially reset by the client it is meant to restrict.

Attack Vector

An unauthenticated remote attacker sends repeated POST requests to the dashboard login endpoint. On each request, the attacker sets a different X-Forwarded-For value (for example, a randomly generated IPv4 address). Because every value produces a new bucket, the attacker can iterate a password dictionary at the full rate the server accepts, without ever triggering the 5-attempt lock or progressive delay.

javascript
// Patch excerpt: cli/cli.js — prefer custom-server.js which injects the real socket IP
// Find standalone server (bundled in bin/app for published package).
// Prefer custom-server.js (injects real socket IP) when present.
const standaloneDir = path.join(__dirname, "app");
const customServerPath = path.join(standaloneDir, "custom-server.js");
const serverPath = fs.existsSync(customServerPath)
  ? customServerPath
  : path.join(standaloneDir, "server.js");

if (!fs.existsSync(serverPath)) {
  console.error("Error: Standalone build not found.");
}
// Source: https://github.com/decolua/9router/commit/7648c3412b403a29f04967c4b4e9725e228791d4

Detection Methods for CVE-2026-55501

Indicators of Compromise

  • High volume of POST requests to the dashboard login route from a single source IP but with varying X-Forwarded-For header values.
  • Login attempts with X-Forwarded-For values that do not correspond to any known upstream proxy in the environment.
  • Successive authentication failures without any corresponding lockout events in application logs.

Detection Strategies

  • Correlate the socket peer IP with X-Forwarded-For in web server or reverse proxy logs and alert when a single peer submits many distinct forwarded values within a short window.
  • Alert on authentication failure counts to the 9Router dashboard exceeding five per source socket IP where no lockout is recorded in application state.
  • Deploy WAF rules that reject or normalize X-Forwarded-For for requests not originating from allow-listed proxies.

Monitoring Recommendations

  • Ingest 9Router application logs and upstream proxy access logs into a central SIEM to enable cross-log correlation of forwarded headers and peer addresses.
  • Track the ratio of failed to successful logins per dashboard host and alert on sudden increases.
  • Monitor for spikes in unique X-Forwarded-For values per user-agent or per TLS session over rolling five-minute windows.

How to Mitigate CVE-2026-55501

Immediate Actions Required

  • Upgrade 9Router to version 0.4.80 or later, which introduces real client IP rate-limiting and a remote default-password guard.
  • Rotate the dashboard password and any credentials that may have been targeted by brute-force attempts prior to patching.
  • Restrict network access to the dashboard interface to trusted management networks or place it behind a VPN.

Patch Information

The fix is available in GitHub Release v0.4.80. The upstream commit 7648c34 replaces the header-based identity source by introducing a custom-server.js that injects the real socket IP into request handling, so loginLimiter.js derives its bucket key from the TCP peer rather than the X-Forwarded-For header. Full details are in GitHub Security Advisory GHSA-7cfm-pqrj-xgq7.

Workarounds

  • Deploy a reverse proxy or WAF in front of 9Router that strips or overwrites X-Forwarded-For from external clients before the request reaches the application.
  • Enforce IP allow-listing on the dashboard login endpoint so only known administrator source addresses can reach /api/auth/login.
  • Add an external rate limit at the proxy layer keyed on the TCP peer address to cap login attempts independent of the application-level limiter.
bash
# Example nginx configuration: strip client-supplied X-Forwarded-For and rate-limit login attempts by peer IP
limit_req_zone $binary_remote_addr zone=9router_login:10m rate=5r/m;

server {
    listen 443 ssl;
    server_name 9router.example.com;

    location /api/auth/login {
        limit_req zone=9router_login burst=5 nodelay;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://127.0.0.1:3000;
    }
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.