Back to Intelligence

15,465 Exposed MCP Servers: Hardening and Detection Guide for Publicly Reachable Model Context Protocol Deployments

SA
Security Arsenal Team
October 6, 2026
14 min read

The Model Context Protocol was designed to do for AI agents what USB-C did for peripherals: one standard interface connecting models, agents, and IDEs to tools and data. By that measure, MCP succeeded beyond anyone's expectations. What the ecosystem failed to do — as new research from OX Security makes painfully clear — is ship with a security model anyone actually implemented.

OX Security's team scanned the public internet and identified 15,465 publicly reachable MCP servers, the overwhelming majority deployed with little or no authentication, exposed tool-execution endpoints, and in many cases direct pathways to command execution, internal data stores, and cloud credentials. The same research effort earlier traced critical vulnerabilities in Anthropic's own MCP reference tooling — a reminder that even the protocol's canonical implementations have shipped exploitable weaknesses.

For defenders, this is the moment MCP stops being an AI-curiosity and becomes attack surface. If your developers stood up an MCP server to wire Claude, Cursor, or an internal agent into Jira, GitHub, a database, or a shell tool — and that server is reachable beyond localhost — you likely have an unauthenticated remote procedure call interface to your internal environment sitting on the internet. This post breaks down the threat model, what OX found, and gives you concrete detection content and hardening steps to act on today.

Technical Analysis

What MCP Servers Actually Expose

An MCP server is, functionally, a JSON-RPC service that advertises tools (functions the model can invoke), resources (data the model can read), and prompts. The two dominant transports are:

  • stdio — the server runs as a local child process of the client (typical for desktop IDE integrations, usually launched via npx, uvx, or a direct binary).
  • HTTP/SSE (Server-Sent Events) — the server listens on a TCP port, clients connect over HTTP, exchange JSON-RPC messages (commonly on endpoints such as /sse and /messages), and invoke tools remotely.

The second transport is where the 15,465-server problem lives. The MCP specification's original authorization guidance was optional, and the vast majority of community-built servers — file system tools, database connectors, shell executors, browser automation, cloud CLIs — were written assuming a trusted local client. Developers then put them on VPS instances, Kubernetes ingresses, and cloud load balancers so remote agents and teammates could reach them. The result is an internet-facing RPC layer where any unauthenticated client can enumerate available tools (tools/list) and invoke them (tools/call).

The Attack Chain (Defender's View)

From an attacker's perspective, the exploitation chain against an exposed MCP server is trivially short:

  1. Discovery — Internet-wide scanning (the same technique OX used) identifies MCP servers by fingerprinting SSE endpoints, JSON-RPC banner behavior, and characteristic response structures. Default deployments frequently listen on common ports (3000, 8000, 8080) with identifiable path patterns.
  2. Enumeration — An unauthenticated tools/list JSON-RPC call returns the full tool manifest: names, descriptions, and input schemas. Tool names like execute_command, run_shell, read_file, query_database, or aws_cli tell the attacker exactly what the server can do — and these manifests are effectively a reconnaissance gift.
  3. Invocation — A tools/call request with attacker-controlled arguments executes the underlying function. Shell-wrapping tools yield direct RCE. File tools yield arbitrary read/write. Database connectors yield data exfiltration. Even seemingly benign tools can be chained into SSRF (fetch tools), credential theft (environment-variable readers), or internal pivoting.
  4. Post-exploitation — MCP servers typically run with the privileges of the service account that launched them, which in container deployments often means mounted cloud credentials, kubeconfig files, and network access to internal services.

Critically, OX Security's earlier work on Anthropic's MCP reference tooling demonstrated that the weaknesses are not limited to misconfiguration — the implementations themselves have carried critical vulnerabilities. That dual reality (insecure-by-default configuration plus implementation flaws) is what makes this an ecosystem-level problem rather than a patch-one-CVE problem. No CVE identifiers have been published in the source reporting for the internet-wide exposure findings; this is an architectural and deployment failure mode, and it must be treated as such.

Exploitation Status

  • Public exposure: Confirmed at scale — 15,465 servers enumerated by a single research team. Assume automated scanners have the same or better visibility.
  • In-the-wild exploitation: The reporting does not confirm mass exploitation, but the barrier to abuse is a single unauthenticated HTTP request. Given the volume of internet-wide scanning traffic in 2026, assume exposed tool-invocation endpoints are being probed.
  • CISA KEV: No MCP-related entries as of publication.
  • PoC availability: The exploitation technique requires no exploit code — it is native protocol functionality invoked over the network.

Why This Is Different From a Normal Exposed Service

Two properties make exposed MCP servers worse than, say, an open Redis instance. First, the tool manifest is self-documenting — the server tells the attacker exactly what it can do and what arguments to send. Second, MCP servers are deliberately wired into high-value backends: production databases, CI/CD systems, cloud control planes, source code repositories, and internal wikis. They were built to be privileged bridges. An exposed one is a privileged bridge with the drawbridge down.

Detection & Response

What You Can Actually Observe

Because MCP tool invocation rides ordinary HTTP/JSON, network signatures alone are weak — the highest-fidelity telemetry is on the endpoint and process layer. The most reliable behavioral indicators:

  • MCP server processes (launched via npx, uvx, node, python, or compiled binaries) listening on non-loopback interfaces — this is the exposure condition itself.
  • MCP server processes spawning child shells or interpreters — legitimate tool execution exists, but cmd.exe, powershell.exe, bash -c, curl, wget, or scripting engines as children of an MCP server warrant scrutiny, especially when arguments look interactive or encoded.
  • Inbound connections to SSE/JSON-RPC endpoints from IPs outside your known agent/client population.

The following detections are tuned for those behaviors. As always: baseline your known MCP deployments first, or these will fire on every legitimate developer workstation running a local server.

Sigma Rules

YAML
---
title: MCP Server Process Spawning Shell or Script Interpreter
id: 3f8c2a71-9b4e-4d2a-a6f1-7e5d9c0b1a23
status: experimental
description: Detects MCP server host processes (node, npx, uvx, python) spawning command shells or script interpreters, consistent with remote tool invocation via an exposed Model Context Protocol server.
references:
  - https://thehackernews.com/2026/10/welcome-to-jungle-what-we-found-inside.html
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/10/15
tags:
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\node.exe'
      - '\npx.exe'
      - '\uvx.exe'
      - '\uv.exe'
      - '\python.exe'
      - '\pythonw.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\mshta.exe'
      - '\curl.exe'
      - '\wget.exe'
  filter_known_tools:
    CommandLine|contains:
      - 'npm install'
      - 'npm run'
      - 'node_modules'
  condition: selection_parent and selection_child and not filter_known_tools
falsepositives:
  - Legitimate MCP tool servers that wrap build or CLI utilities (baseline known MCP server command lines and tune by ParentCommandLine)
  - Development workstations running local stdio MCP servers
level: high
---
title: MCP Server Listening on Non-Loopback Interface (Linux)
id: 8a1d4f62-3c7b-4e9a-b2d5-6f0a8e1c4b97
status: experimental
description: Detects common MCP server runtimes binding network listeners, indicating a Model Context Protocol server exposed beyond localhost on Linux hosts.
references:
  - https://thehackernews.com/2026/10/welcome-to-jungle-what-we-found-inside.html
  - https://attack.mitre.org/techniques/T1071.001/
author: Security Arsenal
date: 2026/10/15
tags:
  - attack.command_and_control
  - attack.t1071.001
logsource:
  category: process_creation
  product: linux
detection:
  selection_runtime:
    Image|endswith:
      - '/node'
      - '/npx'
      - '/uvx'
      - '/python'
      - '/python3'
  selection_args:
    CommandLine|contains:
      - 'mcp'
      - 'sse'
      - '--port'
      - '--host 0.0.0.0'
      - 'server.py'
  condition: selection_runtime and selection_args
falsepositives:
  - Intended internal MCP deployments (validate listener bind address with the VQL hunt below and firewall posture)
level: medium
---
title: Inbound Connection to MCP SSE Endpoint from External Source
id: 5c9e7b13-2f4a-4d8c-91e6-0b3a7f2d5e48
status: experimental
description: Detects HTTP requests to characteristic MCP Server-Sent Events and JSON-RPC message endpoints, which may indicate probing or unauthenticated tool invocation against an exposed server.
references:
  - https://thehackernews.com/2026/10/10/welcome-to-jungle-what-we-found-inside.html
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/10/15
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: webserver
detection:
  selection_path:
    cs-uri|contains:
      - '/sse'
      - '/messages'
      - '/mcp'
  selection_method:
    cs-method:
      - 'POST'
      - 'GET'
  condition: selection_path and selection_method
falsepositives:
  - Legitimate MCP client traffic from authorized agents (scope by source IP allowlist in your SIEM correlation layer)
  - Other applications using /messages paths
level: medium

Note: the third rule is intentionally broad at the log source and should be correlated with external source IPs at the SIEM layer — it is a hunting pivot, not a fire-and-forget alert.

KQL — Microsoft Sentinel / Defender

KQL — Microsoft Sentinel / Defender
// Hunt: MCP server runtimes launching on endpoints, with focus on network-exposed and shell-spawning behavior
// Covers Windows (DeviceProcessEvents) and Linux via Syslog ingestion

// Part 1: MCP runtime processes spawning shells or download tools (Windows)
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("node.exe", "npx.exe", "uvx.exe", "uv.exe", "python.exe", "pythonw.exe")
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "mshta.exe", "wscript.exe", "curl.exe", "wget.exe")
| where ProcessCommandLine !has_any ("npm install", "npm run", "node_modules")
| summarize FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), count() 
    by DeviceName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, AccountName
| order by LastSeen desc;

// Part 2: Correlate MCP runtimes with inbound network connections (exposure indicator)
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("node.exe", "npx.exe", "uvx.exe", "python.exe", "python3")
| where ActionType == "InboundConnectionAccepted" or (RemoteIPType == "Public" and ActionType == "ConnectionSuccess")
| extend MCPIndicator = iff(InitiatingProcessCommandLine has_any ("mcp", "sse", "server"), "LikelyMCP", "Review")
| summarize Connections = count(), DistinctRemoteIPs = dcount(RemoteIP), RemoteIPs = make_set(RemoteIP, 20)
    by DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, LocalPort, MCPIndicator
| order by DistinctRemoteIPs desc;

// Part 3: Linux Syslog hunt for MCP servers bound to all interfaces
Syslog
| where TimeGenerated > ago(7d)
| where ProcessName has_any ("node", "python", "uvx", "npx") or SyslogMessage has "mcp"
| where SyslogMessage has_any ("0.0.0.0", "--host", "/sse", "tools/call", "tools/list", "jsonrpc")
| project TimeGenerated, Computer, ProcessName, SyslogMessage
| order by TimeGenerated desc;

Velociraptor VQL

VQL — Velociraptor
-- Hunt: Identify running MCP server processes and their network listeners
-- Deploy as a hunt across the fleet to inventory MCP exposure

SELECT Pid,
       Name,
       CommandLine,
       Exe,
       Username,
       CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)(mcp|model.context.protocol|/sse|tools/call)'
   OR Exe =~ '(?i)(mcp-server|mcp_server)'
VQL — Velociraptor
-- Hunt: Enumerate listeners owned by common MCP runtimes (exposure condition)
-- A listener on 0.0.0.0 or a routable address owned by node/python/uvx is a triage priority

SELECT Process.Name AS ProcessName,
       Process.Pid AS Pid,
       Process.CommandLine AS CommandLine,
       Address AS BindAddress,
       Port AS BindPort,
       Status
FROM netstat()
WHERE Status = 'LISTEN'
  AND Process.Name =~ '(?i)(node|python|uvx|uv|deno|bun)'
  AND Address !~ '^(127\.|::1|\[::1\])'

Remediation Script — Audit and Contain Exposed MCP Listeners

Bash / Shell
#!/usr/bin/env bash
# mcp-exposure-audit.sh — Inventory MCP servers and flag network-exposed listeners
# Run on Linux hosts (and via WSL/containers). Requires: ss, awk. Run as root for full visibility.

set -euo pipefail

echo "=== [1/3] MCP-related running processes ==="
ps -eo pid,user,comm,args | grep -iE 'mcp|model.?context|/sse' | grep -v grep || echo "No MCP-related processes found."

echo ""
echo "=== [2/3] Non-loopback listeners owned by common MCP runtimes ==="
# Flag any node/python/uvx/deno/bun process listening beyond localhost
ss -tlnp 2>/dev/null | awk 'NR>1 {print $4, $0}' | grep -vE '^(127\.|\[::1\]|::1)' \
  | grep -iE 'node|python|uvx|deno|bun' || echo "No exposed runtime listeners detected."

echo ""
echo "=== [3/3] Containment: bind-check common MCP configs ==="
# Review MCP client/server configs for remote transport definitions lacking auth
for cfg in "$HOME/.cursor/mcp.json" "$HOME/.config/Claude/claude_desktop_config.json" \
           "$HOME/.vscode/mcp.json" /etc/mcp/*.json /opt/*/mcp.json; do
  [ -f "$cfg" ] || continue
  echo "--- $cfg ---"
  grep -iE '"(url|host|port|sse|transport)"' "$cfg" || echo "  (no remote transport keys found)"
  if grep -qiE '"url".*https?://' "$cfg" && ! grep -qiE 'auth|token|oauth|api[_-]?key' "$cfg"; then
    echo "  [WARNING] Remote MCP transport configured with NO apparent authentication in $cfg"
  fi
done

echo ""
echo "=== ACTION ITEMS ==="
echo "1. Any MCP server bound to 0.0.0.0 without an auth layer must be taken offline or re-bound to 127.0.0.1 NOW."
echo "2. Place required remote MCP servers behind an authenticated reverse proxy (mTLS or OAuth 2.1 per current MCP auth spec)."
echo "3. Firewall: deny inbound to MCP service ports from anything except your authorized agent/client CIDRs."
echo "4. Rotate any credentials, tokens, or cloud keys accessible to hosts that ran an exposed MCP server."
PowerShell
# mcp-exposure-audit.ps1 — Windows fleet audit for exposed MCP servers
# Run elevated. Deploy via your RMM/Intune for fleet-wide coverage.

Write-Host "=== [1/3] MCP-related running processes ==="
Get-CimInstance Win32_Process |
  Where-Object { $_.CommandLine -match '(?i)mcp|model.?context|/sse|tools/call' } |
  Select-Object ProcessId, Name, CommandLine, @{N='User';E={$_.GetOwner().User}} |
  Format-List

Write-Host "=== [2/3] Non-loopback listeners owned by MCP runtimes ==="
$runtimePids = Get-Process -Name node,python,pythonw,uvx,deno,bun -ErrorAction SilentlyContinue |
  Select-Object -ExpandProperty Id
Get-NetTCPConnection -State Listen -ErrorAction SilentlyContinue |
  Where-Object { $_.OwningProcess -in $runtimePids -and
                 $_.LocalAddress -notin @('127.0.0.1','::1') } |
  ForEach-Object {
    $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
    [PSCustomObject]@{
      LocalAddress = $_.LocalAddress
      LocalPort    = $_.LocalPort
      Process      = $proc.ProcessName
      Path         = $proc.Path
      Risk         = 'EXPOSED - MCP runtime listening on non-loopback'
    }
  } | Format-Table -AutoSize

Write-Host "=== [3/3] MCP client configs with unauthenticated remote transports ==="
$cfgPaths = @(
  "$env:USERPROFILE\.cursor\mcp.json",
  "$env:APPDATA\Claude\claude_desktop_config.json",
  "$env:USERPROFILE\.vscode\mcp.json"
)
foreach ($cfg in $cfgPaths) {
  if (Test-Path $cfg) {
    $raw = Get-Content $cfg -Raw
    if ($raw -match '"url"\s*:\s*"https?://' -and $raw -notmatch '(?i)auth|token|oauth|api[_-]?key') {
      Write-Warning "Remote MCP transport with NO apparent authentication: $cfg"
    } else {
      Write-Host "OK: $cfg (no unauthenticated remote transport detected)"
    }
  }
}

Write-Host "`n=== CONTAINMENT ==="
Write-Host "1. Stop and re-bind any exposed MCP server to 127.0.0.1 immediately."
Write-Host "2. Enforce OAuth 2.1 / mTLS on any MCP server that must be remotely reachable."
Write-Host "3. Block inbound MCP ports at the host firewall for all but authorized client CIDRs:"
Write-Host '   New-NetFirewallRule -DisplayName "Block Public MCP" -Direction Inbound -LocalPort 3000,8000,8080 -Protocol TCP -RemoteAddress Internet -Action Block'
Write-Host "4. Rotate credentials reachable from hosts that ran exposed MCP servers (cloud keys, DB passwords, API tokens)."

Remediation

There is no single patch for this problem — it is a deployment-model failure. Remediate in this order:

Immediate (today):

  1. Inventory your MCP footprint. Run the audit scripts above fleet-wide and query your external attack surface management tooling (Shodan/Censys exposure data, EASM platform) for SSE endpoints and MCP fingerprints on your public ranges. If OX found 15,465 servers, scanners know where yours are.
  2. Take exposed unauthenticated servers offline or re-bind to loopback. Any MCP server listening on 0.0.0.0 without authentication is a pre-authentication RPC interface to your environment. Treat discovery of one as a security incident, not a misconfiguration ticket.
  3. Rotate credentials. Any host that ran an internet-exposed MCP server with tool access to databases, cloud APIs, or source control should have those credentials rotated. Assume tools/list and tools/call were exercised.

Short term (this week): 4. Enforce authentication per the current MCP authorization specification — OAuth 2.1-based flows for remote HTTP transports, or mTLS at a minimum via an authenticating reverse proxy (nginx, Envoy, Caddy) in front of any MCP server that must be network-reachable. 5. Network segmentation. MCP servers belong in a dedicated segment with egress restricted to only the backends their tools require. An MCP server that can reach your entire internal network is a lateral-movement amplifier by design. 6. Principle of least tooling. Audit every deployed server's tool manifest. Remove shell-execution, arbitrary file-write, and cloud-CLI tools from any server reachable by agents that don't strictly need them. Every tool you expose is an attack primitive. 7. Update MCP SDKs and reference implementations. OX Security's prior research identified critical vulnerabilities in Anthropic's MCP tooling specifically — track the official MCP project repositories and Anthropic's security advisories, and pin/patch SDK dependencies in your builds. Subscribe to the project's GitHub security advisories and the protocol's changelog.

Strategic (this quarter): 8. Govern AI tooling like you govern APIs. MCP servers are internal APIs with an LLM on the client side — put them through the same design review, authentication requirements, and change control as any service that touches production data. 9. Add MCP to your threat model and pen test scope. Tool-invocation authorization, prompt-injection-driven tool abuse, and cross-server trust relationships should be standing test cases in 2026 assessments. 10. Deploy the detections above and baseline your legitimate MCP deployments so the Sigma and KQL content alerts on deviation rather than normal operations.

Executive Takeaway

MCP is becoming the connective tissue of enterprise AI, and right now a large share of that tissue is exposed, unauthenticated, and holding the keys to internal systems. The OX Security findings are not a curiosity — they are a measurement of your likely exposure. Inventory, authenticate, segment, and monitor before the exploitation statistics catch up to the exposure statistics.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.