CVE-2026-48814: Network-AI: Empty default secret still authorizes all requests (Incomplete fix for CVE-2026-46701)
Advisory / Disclosure
Network-AI — CVE-2026-46701 fix is incomplete: the "Empty Default Secret" unauth path survives
Target: Jovancoding/Network-AI (npm network-ai), latest v5.7.1 Status: the advisory ("Unauthenticated Cross-Origin MCP Tool Invocation via Empty Default Secret") named three flaws. The fix (5.4.5) closed the CORS flaw (Access-Control-Allow-Origin is now set only for localhost origins), but left the empty-default-secret flaw the title is about: the SSE MCP server still defaults to an empty secret, isAuthorized() still returns true when the secret is empty, and a non-loopback bind only warns. So the server still runs fully unauthenticated by default — any non-browser caller (curl, SSRF, or a 0.0.0.0 bind) can invoke all 22 MCP tools (configset, agentspawn, blackboardwrite, token) with no credentials. Class: CWE-306/CWE-862 Missing Authentication — incomplete fix. Methodology: M1 incomplete-fix audit (anchor = the 5.4.5 fix; sibling-walk on latest v5.7.1, executed). Severity: High (matches parent; the browser amplifier is removed, so exploitation now needs non-browser reach — SSRF or a non-loopback bind, which the fix only warns about).
What the fix did and didn't do (verified on latest v5.7.1) | advisory flaw | latest v5.7.1 | |---|---| | wildcard CORS (ACAO: ) | FIXED — lib/mcp-transport-sse.ts sets ACAO only when origin matches ^https?://(localhost\|127\.0\.0\.1)(:\d+)?$ | | empty default secret | NOT FIXED — bin/mcp-server.ts: secret: process.env['NETWORKAIMCPSECRET'] ?? '' | | isAuthorized open on empty secret | NOT FIXED — if (!this.opts.secret) return true; | | require secret / refuse unauth bind | NOT DONE — listen() only process.stderr.write('… WARNING …') on non-loopback bind, then listens anyway |
The advisory's remediation #1 ("Require a non-empty secret at startup … process.exit(1)") was not implemented.
PoC (executed against the latest source, v5.7.1) — poc/legend-networkai-empty-secret.ts Instantiates the real McpSseServer from the latest lib/ with a mock bridge and the default (empty) secret, then issues requests (run-log poc/run-log.txt):
POST /mcp no-auth, no-origin (curl/SSRF) -> HTTP 200, dispatched=true body: {"jsonrpc":"2.0","id":1,"result":{"executed":true,"tool":"configset"}} POST /mcp Origin: evil.example.com -> ACAO=undefined (CORS half fixed) The no-auth request passes isAuthorized and reaches handleRPC (tool dispatched) — i.e. unauthenticated tool invocation persists on the latest release; only the browser-CORS read amplifier was removed.
Run: from a v5.7.1 checkout, npm i then npx ts-node --transpile-only poc/legend-networkai-empty-secret.ts.
Recommended fix Implement the advisory's remediation #1: refuse to start SSE mode with an empty secret (unless --stdio), and/or change isAuthorized to fail closed (an empty configured secret should mean "deny", not "allow"). The CORS allowlist alone does not authenticate non-browser callers.
Precondition / honesty With CORS now localhost-only, the drive-by browser attack is mitigated. The residual requires a non-browser path to the port: an SSRF on the host, or the operator binding to a non-loopback address (Docker/remote), which the fix only warns about. The empty secret remains the shipped default and isAuthorized still authorizes it.
Credits
@Kai Aizen / @SnailSploit — https://snailsploit.com
Other sources
Network-AI is a TypeScript/Node.js multi-agent orchestrator. In versions 5.7.1 and earlier, the MCP SSE server allows unauthenticated cross-origin MCP tool invocation due to an empty default secret. This issue was partially addressed by CVE-2026-46701 in version 5.4.5 by closing the CORS flaw (with Access-Control-Allow-Origin now set only for localhost origins), but the empty-default-secret flaw described in the title remained: the SSE MCP server still defaulted to an empty secret, isAuthorized() still returned true when the secret was empty, and a non-loopback bind only produced a warning. As a result, the server still ran fully unauthenticated by default. Any non-browser caller (for example, curl, SSRF, or a 0.0.0.0 bind) could invoke all 22 MCP tools (configset, agentspawn, blackboardwrite, token) with no credentials. This issue was fixed in version 5.7.2.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/network-aito a version that resolves this vulnerability.Fixed in 5.7.2 - Configuration
Require NETWORK_AI_MCP_SECRET be set to a non-empty value before starting SSE mode; if the environment variable is empty or unset, refuse to start SSE mode and exit the process (e.g., call process.exit(1)).
bin/mcp-server.ts (SSE startup) NETWORK_AI_MCP_SECRET = non-empty string - Configuration
Modify _isAuthorized so that an empty configured secret does NOT authorize requests (fail closed). Remove or change the code path 'if (!this._opts.secret) return true;' so that it returns false/denies when the secret is empty.
McpSseServer._isAuthorized (lib) _isAuthorized empty-secret behavior = deny (return false)
Event History
Frequently Asked Questions
What is the severity of CVE-2026-48814?
The severity of CVE-2026-48814 is critical with a CVSS score of 9.1.
What are the risks associated with CVE-2026-48814?
CVE-2026-48814 allows unauthenticated cross-origin requests due to an empty default secret, potentially leading to unauthorized access.
How do I fix CVE-2026-48814?
To fix CVE-2026-48814, upgrade to Network-AI version 5.7.2 or later, which includes a complete resolution for this vulnerability.
What versions are affected by CVE-2026-48814?
CVE-2026-48814 affects Network-AI versions 5.7.1 and earlier.
Is CVE-2026-48814 related to any previous vulnerabilities?
Yes, CVE-2026-48814 is an incomplete fix for the earlier CVE-2026-46701.