Broken Authentication

Broken Authentication in Node.js/Express CVE-2026-42856 [CVE-2026-42856]

[Fixed 2026-05] Updated CVE-2026-42856

Overview

CVE-2026-42856 describes a Broken Authentication vulnerability in Network-AI's MCP HTTP transport where JSON-RPC tool calls were accepted without authentication, session, origin, or token checks and dispatched directly to the orchestrator's tool registry. This CWE-306 vulnerability means an attacker with network visibility could enumerate and invoke privileged management tools exposed by the service. In Node.js/Express deployments that mirror this insecure pattern, similar risks arise when a JSON-RPC or RPC-like endpoint is exposed without proper auth checks, allowing abuse of sensitive operations. Prior to the fix in 5.1.3, the MCP HTTP transport would forward requests that contained tool names and parameters straight to the internal tool registry, effectively bypassing authorization controls. The default bind address being 0.0.0.0 meant insecure services were reachable from anywhere on the network, enabling unauthorized control of privileged tooling. This guide maps the real-world impact of that class of vulnerability to Node.js/Express code patterns and provides concrete remediation examples. Remediation for Node.js/Express focuses on enforcing authentication and authorization, restricting network exposure, and validating every RPC call. Use token-based or session-based auth for privileged endpoints, whitelist allowed tools, ensure the server binds only to restricted interfaces, and enable transport protections (TLS). Additional hardening includes input validation, rate limiting, and comprehensive auditing to detect abuse of RPC-like endpoints across deployments. This guide demonstrates a concrete vulnerable pattern and a secure alternative in Node.js/Express, showing how to avoid the pitfalls highlighted by CVE-2026-42856 and CWE-306.

Affected Versions

≤5.1.2

Code Fix Example

Node.js (Express) API Security Remediation
// Vulnerable pattern: no auth, exposed RPC over 0.0.0.0
const express = require('express');
const app = express();
app.use(express.json());

const toolRegistry = {
  getTime: () => new Date().toISOString(),
  shutdown: () => 'shutdown-initiated'
};

app.post('/rpc', (req, res) => {
  const { tool, params } = req.body;
  const fn = toolRegistry[tool];
  if (typeof fn !== 'function') {
    return res.status(400).json({ error: 'Unknown tool' });
  }
  // Vulnerable: no auth, directly dispatches to registry
  const result = fn(params);
  res.json({ result });
});

app.listen(3000, '0.0.0.0', () => {
  console.log('Vulnerable RPC service listening on 0.0.0.0:3000');
});


// Secure version: authenticate, authorize, and restrict exposure
const jwt = require('jsonwebtoken');
const SECRET = process.env.RPC_ADMIN_SECRET || 'change-me';

const secureTools = {
  getTime: () => new Date().toISOString()
};

function requireAuth(req, res, next) {
  const auth = req.headers['authorization'];
  if (!auth) return res.status(401).json({ error: 'Unauthorized' });
  const parts = auth.split(' ');
  if (parts.length !== 2 || parts[0] !== 'Bearer') {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  const token = parts[1];
  try {
    jwt.verify(token, SECRET);
    next();
  } catch (e) {
    res.status(403).json({ error: 'Forbidden' });
  }
}

const secureApp = express();
secureApp.use(express.json());

secureApp.post('/rpc', requireAuth, (req, res) => {
  const { tool, params } = req.body;
  const fn = secureTools[tool];
  if (typeof fn !== 'function') {
    return res.status(400).json({ error: 'Unknown tool' });
  }
  const result = fn(params);
  res.json({ result });
});

// Bind to localhost to avoid public exposure; encourage TLS in fronting proxy
secureApp.listen(3001, '127.0.0.1', () => {
  console.log('Secure RPC service listening on 127.0.0.1:3001');
});

CVE References

Choose which optional cookies to allow. You can change this any time.