CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

CVE-2026-55501

highCVSS 7.3covered by 2 sourcesfirst seen 2026-07-06
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 lim

⚡ Watch CVE-2026-55501

Get an email if CVE-2026-55501 is added to CISA KEV, gains public exploit code, or a new advisory cites it — max one per day, one-click unsubscribe.

Advisory coverage (2)

External references

NVD record for CVE-2026-55501

CVE.org record

Embed the live status

CVE-2026-55501 live status badge — this badge updates automatically when the KEV or exploit status changes. How to embed it →

[![CVE-2026-55501 status](https://www.csirts.com/badge/CVE-2026-55501)](https://www.csirts.com/cve/CVE-2026-55501)