The Model Context Protocol (MCP) has become the de facto standard for connecting AI agents to enterprise tools and data. Anthropic open-sourced it, major LLM clients adopted it, and development teams everywhere are now spinning up MCP servers to give copilots access to filesystems, databases, ticketing systems, cloud APIs, and internal wikis. That adoption has outpaced security review by a wide margin.
The exposure pattern is consistent and, frankly, predictable to anyone who lived through the early days of CI/CD pipeline sprawl: MCP servers frequently run with plaintext credentials sitting in local configuration files, they're granted far broader access to downstream systems than the use case requires, and they accept instructions from LLM contexts that can be manipulated through prompt injection. The kicker is that in most organizations, these servers are deployed by individual developers or small teams without any ticket, change control, or security notification. The security team doesn't know the server exists until an incident — or a hunt — finds it.
This post breaks down the three primary exposure vectors, gives you working detection content to find MCP servers operating in your environment, and lays out a hardening baseline you can enforce today.
Technical Analysis: How MCP Servers Expose Secrets
1. Plaintext Secrets in MCP Configuration Files
MCP clients (Claude Desktop, Cursor, Windsurf, VS Code with Copilot agent mode, and others) store server definitions and their environment variables — including API tokens, database connection strings, and cloud credentials — in local JSON configuration files. Common locations include:
%APPDATA%\Claude\claude_desktop_config.json(Windows)~/Library/Application Support/Claude/claude_desktop_config.json(macOS)~/.cursor/mcp.json,.vscode/mcp.json, project-levelmcp.jsonfiles- Adjacent
.envfiles referenced by the server process
These files are typically world-readable within the user's context, committed to git repositories by accident with alarming frequency, and backed up to cloud sync folders. Any process running as the user — including commodity stealer malware that already keys on config.json and .env patterns — can harvest them. This is the same blast radius pattern we've seen with AWS credentials in ~/.aws/credentials, except MCP configs aggregate secrets for multiple downstream systems in one file.
2. Over-Permissioned Access
MCP servers act as a proxy identity. When a developer configures an MCP server for PostgreSQL with a read/write service account, or a GitHub MCP server with a personal access token scoped to repo (full control), every operation the AI agent performs inherits those permissions. The agent becomes a confused deputy: the human's intent is filtered through an LLM, and the LLM's instructions execute with service-account privilege. There is no native concept of least privilege, per-operation approval, or row-level scoping in most MCP server implementations today. Audit attribution also collapses — downstream logs show the service account, not the user or the prompt that drove the action.
3. Prompt Injection as a Secret-Exfiltration Primitive
This is the vector that turns a local misconfiguration into an enterprise incident. If an MCP-connected agent ingests attacker-controlled content — a malicious README in a repo, a crafted Jira ticket, a poisoned web page, an email body — that content can instruct the agent to invoke its tools to read credential files, query secrets stores, or package sensitive data and send it to an external endpoint. Because the agent's tool calls are legitimate function invocations executed by the MCP server, traditional egress and execution controls see normal process behavior. The MCP server is doing exactly what it was configured to do; it's the instructions that are hostile. Combined with vector #2 (over-permissioned tokens) and vector #1 (secrets sitting on disk), a single successful indirect prompt injection can cascade into full credential compromise across every system the MCP server touches.
Exploitation Status
No specific CVE is associated with this reporting — this is an architectural exposure class, not a single patchable flaw. However, prompt injection against tool-using agents is an actively demonstrated and exploited technique in 2025–2026, and public research continues to show MCP servers shipped with insufficient input validation and overly broad default scopes. Treat any MCP server in your environment as a privileged, internet-adjacent service until proven otherwise.
Detection & Response
The detections below focus on the three observable behaviors: unauthorized access to MCP configuration files, MCP server processes spawning shells or network tools (a strong post-injection indicator), and discovery of MCP servers you didn't know were running.
---
title: Suspicious Access to MCP Configuration Files
id: 3f8a1c42-7b5d-4e91-a6c3-9d2e8f1a4b07
status: experimental
description: Detects processes outside known MCP clients reading MCP server configuration files, which commonly contain plaintext API tokens and connection strings.
references:
- https://attack.mitre.org/techniques/T1552/001/
author: Security Arsenal
date: 2026/08/14
tags:
- attack.credential_access
- attack.t1552.001
logsource:
category: file_event
product: windows
detection:
selection_path:
TargetFilename|contains:
- '\claude_desktop_config.json'
- '\mcp.json'
- '\.cursor\mcp.json'
- '\.vscode\mcp.json'
filter_clients:
Image|endswith:
- '\Claude.exe'
- '\Cursor.exe'
- '\Code.exe'
- '\explorer.exe'
condition: selection_path and not filter_clients
falsepositives:
- Developers manually editing MCP configuration files in other editors
- Backup and sync agents (OneDrive, Dropbox) touching user config paths
level: medium
---
title: MCP Server Process Spawning Shell or Network Tool
id: 6c2d9e15-4a8f-4b37-9c1e-2f7a5d8b3e60
status: experimental
description: Detects MCP server runtimes (node, python, uvx, npx) spawning shells, download cradles, or exfiltration tools — a high-fidelity indicator of prompt injection driving tool abuse.
references:
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/08/14
tags:
- attack.execution
- attack.t1059
- attack.exfiltration
- attack.t1041
logsource:
category: process_creation
product: windows
detection:
selection_parent:
ParentImage|endswith:
- '\node.exe'
- '\python.exe'
- '\uvx.exe'
- '\npx.exe'
- '\bun.exe'
- '\deno.exe'
selection_parent_cmd:
ParentCommandLine|contains:
- 'mcp'
selection_child:
Image|endswith:
- '\cmd.exe'
- '\powershell.exe'
- '\pwsh.exe'
- '\curl.exe'
- '\wget.exe'
- '\certutil.exe'
- '\bitsadmin.exe'
- '\rclone.exe'
- '\tar.exe'
condition: selection_parent and selection_parent_cmd and selection_child
falsepositives:
- MCP servers legitimately wrapping CLI tools (e.g., git, cloud CLIs) — baseline known servers and tune by ParentCommandLine
level: high
---
title: MCP Server Runtime Launched Outside Approved Client Paths
id: 9e4b7a28-1d6c-4f52-b8a3-5c9e2d7f4a91
status: experimental
description: Identifies MCP server processes started from unusual directories or by unexpected parent processes, surfacing shadow AI agent deployments unknown to security.
references:
- https://attack.mitre.org/techniques/T1105/
author: Security Arsenal
date: 2026/08/14
tags:
- attack.discovery
- attack.command_and_control
logsource:
category: process_creation
product: windows
detection:
selection_cmd:
CommandLine|contains:
- 'mcp-server'
- 'server-mcp'
- '@modelcontextprotocol'
- 'mcp.run'
- 'mcp_proxy'
filter_approved:
ParentImage|endswith:
- '\Claude.exe'
- '\Cursor.exe'
- '\Code.exe'
condition: selection_cmd and not filter_approved
falsepositives:
- Developers testing MCP servers manually from terminal sessions — investigate and register the deployment rather than suppress
level: medium
// Hunt: MCP server runtimes making outbound network connections or spawning tools
// Useful for finding shadow MCP deployments and post-prompt-injection behavior
let mcp_runtime = dynamic(["node.exe","python.exe","uvx.exe","npx.exe","bun.exe","deno.exe"]);
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where FileName in~ (mcp_runtime)
| where ProcessCommandLine has_any ("mcp", "modelcontextprotocol")
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated),
DistinctHosts=dcount(DeviceName), Commands=make_set(ProcessCommandLine, 10)
by DeviceName, InitiatingProcessAccountName, InitiatingProcessFileName
| extend SuspiciousParent = iff(InitiatingProcessFileName !in~ (
"claude.exe","cursor.exe","code.exe","cmd.exe","powershell.exe","pwsh.exe","windowsterminal.exe"), true, false)
| project FirstSeen, LastSeen, DeviceName, InitiatingProcessAccountName,
InitiatingProcessFileName, SuspiciousParent, Commands
| order by SuspiciousParent desc, FirstSeen asc;
// Correlate: egress from MCP runtimes to non-LLM destinations
DeviceNetworkEvents
| where TimeGenerated > ago(24h)
| where InitiatingProcessFileName in~ (mcp_runtime)
| where InitiatingProcessCommandLine has "mcp"
| where RemoteIPType == "Public"
| summarize Connections=count(), Destinations=make_set(RemoteUrl, 20)
by DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName
| where Connections > 50 or array_length(Destinations) > 5
| order by Connections desc;
-- Hunt: Enumerate MCP server processes and locate MCP config files containing secrets
-- Deploy as a multi-client hunt across Windows, macOS, and Linux fleets
LET procs = SELECT Pid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)mcp|modelcontextprotocol'
AND Name =~ '(?i)node|python|uvx|npx|bun|deno'
LET configs = SELECT FullPath, Size, Mtime, Data.String AS ConfigContent
FROM glob(globs=[
'C:/Users/*/AppData/Roaming/Claude/claude_desktop_config.json',
'C:/Users/*/.cursor/mcp.json',
'C:/Users/*/.vscode/mcp.json',
'/home/*/.config/Claude/claude_desktop_config.json',
'/home/*/.cursor/mcp.json',
'/Users/*/Library/Application Support/Claude/claude_desktop_config.json'
], accessor='file')
WHERE SELECT FullPath FROM parse_file(filename=FullPath, accessor='file')
SELECT * FROM procs
UNION ALL
SELECT NULL AS Pid, 'MCP_CONFIG_FILE' AS Name, FullPath AS CommandLine,
NULL AS Exe, NULL AS Username, Mtime AS CreateTime
FROM configs
# MCP Secret Exposure Audit - run via RMM/Intune/SCCM across endpoints
# Identifies MCP config files and flags embedded plaintext credentials
$mcpPaths = @(
"$env:APPDATA\Claude\claude_desktop_config.json",
"$env:USERPROFILE\.cursor\mcp.json",
"$env:USERPROFILE\.vscode\mcp.json",
"$env:USERPROFILE\.codeium\windsurf\mcp_config.json"
)
$secretPatterns = '(?i)(api[_-]?key|token|secret|password|passwd|connectionstring|Bearer\s+[A-Za-z0-9]|sk-[A-Za-z0-9]{20,}|ghp_[A-Za-z0-9]{20,}|xox[baprs]-|AKIA[0-9A-Z]{16})'
$findings = @()
foreach ($path in $mcpPaths) {
if (Test-Path $path) {
$content = Get-Content $path -Raw -ErrorAction SilentlyContinue
$acl = (Get-Acl $path).AccessToString
$hasSecrets = $content -match $secretPatterns
$findings += [PSCustomObject]@{
ConfigPath = $path
FileSizeKB = [math]::Round((Get-Item $path).Length / 1KB, 2)
LastModified = (Get-Item $path).LastWriteTime
ContainsSecrets = $hasSecrets
ACL = $acl
Risk = if ($hasSecrets) { 'HIGH - plaintext credentials in MCP config' } else { 'INFO - MCP server registered' }
}
Write-Host "[$(if($hasSecrets){'ALERT'}else{'INFO '})] $path" -ForegroundColor $(if($hasSecrets){'Red'}else{'Cyan'})
}
}
# Harden: restrict config ACLs to the owning user where secrets are present
foreach ($f in ($findings | Where-Object ContainsSecrets)) {
$acl = Get-Acl $f.ConfigPath
$acl.SetAccessRuleProtection($true, $false) # disable inheritance
$userRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"$env:USERDOMAIN\$env:USERNAME", 'FullControl', 'Allow')
$acl.ResetAccessRule($userRule)
Set-Acl $f.ConfigPath $acl
Write-Host "Hardened ACL: $($f.ConfigPath)" -ForegroundColor Yellow
}
$findings | Export-Csv -Path "$env:ProgramData\MCP-SecretAudit-$(Get-Date -Format yyyyMMdd).csv" -NoTypeInformation
Write-Host "Audit complete. $($findings.Count) MCP config(s) found. Results exported to ProgramData." -ForegroundColor Green
Remediation and Hardening Baseline
Because this is an architectural exposure rather than a single CVE, remediation is a program of controls rather than a patch. Prioritize in this order:
1. Inventory first. You cannot protect MCP servers you don't know about. Deploy the process-execution hunt above fleet-wide, sweep endpoints and developer workstations for claude_desktop_config.json, mcp.json, and similar artifacts, and pull EDR telemetry for npx/uvx executions referencing MCP packages. Every discovered server gets an owner, a documented purpose, and a risk rating — or it gets disabled.
2. Get secrets out of config files. Move all MCP credentials into a proper secrets manager (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, 1Password Secrets Automation) and reference them at runtime rather than embedding them in JSON. Where the MCP client requires inline env vars, use a wrapper that fetches the secret at launch and never persists it to disk. Add pre-commit hooks (e.g., gitleaks, trufflehog) to catch MCP configs before they hit repositories, and scan existing repo history — assume any config file ever committed is compromised and rotate accordingly.
3. Enforce least privilege on every downstream token. Scope GitHub PATs to specific repositories with read-only where possible. Give database MCP servers read-only roles against non-production datasets by default. Set short TTLs on tokens and rotate on a schedule. Where the downstream system supports it, use per-user OAuth delegation so actions are attributable to the human, not a shared service account.
4. Treat agent output as untrusted code. Gate destructive or sensitive MCP tool calls behind human-in-the-loop approval. Segment MCP servers onto hosts or containers with restricted egress — an MCP server that only needs to reach your internal GitLab has no business making arbitrary outbound HTTPS connections. Monitor for the child-process patterns in the Sigma rules above; a database MCP server spawning curl is never benign.
5. Control prompt-injection surface area. Restrict which data sources an agent can ingest (an agent reading arbitrary web content and holding filesystem tools is a loaded gun). Where supported, pin tool allowlists per session and strip tool descriptions of anything that grants more capability than the task requires. Track emerging MCP security guidance from Anthropic and the MCP specification maintainers — the ecosystem is moving fast, and upstream hardening features are landing regularly.
6. Update policy and detection engineering. Add MCP/AI-agent deployments to your change management and asset inventory requirements explicitly. Fold the hunt queries above into your SOC's standing analytics, and add "AI agent tool abuse" to your tabletop exercise scenarios — your IR runbook for a stolen service token needs a branch for "stolen because an LLM was told to read it."
The organizations that get hurt here won't be the ones that banned MCP outright — they'll be the ones whose developers adopted it quietly, with production credentials, while security looked the other way. Find them first.
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.