DRAFT -- Community contribution, not an official CIS publication. This benchmark is a community-developed draft submitted to the CIS WorkBench for consideration. It has not been reviewed, approved, or published by the Center for Internet Security (CIS). The final benchmark may differ substantially from this draft.
22 security controls across 6 sections for Model Context Protocol (MCP) servers, providing actionable security configuration guidance for enterprise MCP deployments.
| Section | Controls | Profile Mix |
|---|---|---|
| 1. Authentication & Access Control | 4 | 2x L1, 2x L2 |
| 2. Message Integrity | 4 | 2x L1, 2x L2 |
| 3. Audit & Logging | 4 | 2x L1, 2x L2 |
| 4. Network Security | 3 | 3x L1 |
| 5. Supply Chain | 4 | 3x L1, 1x L2 |
| 6. Agent Verification | 3 | 3x L2 |
Version: 1.0.0-draft Date: 2026-03-29 Author: Raza Sharif, CyberSecAI Ltd CIS Community Leader: Andrew Dannenberger Contributing Organization: CyberSecAI Ltd
- OWASP MCP Security Cheat Sheet -- covers MCP security risks, authentication, tool poisoning, and logging guidance
- OWASP MCP Top 10 -- top 10 security risks for Model Context Protocol deployments
- IETF MCPS Specification -- Internet-Draft for cryptographic MCP security (message signing, agent identity, trust model); one possible implementation approach
- EU AI Act -- European regulation on AI systems, referenced throughout for compliance mapping
- Scanner -- automated MCP security scanning
- Protocol -- MCPS protocol reference implementation
The Model Context Protocol (MCP) enables AI agents to interact with external tools, data sources, and services through a standardized interface. As MCP adoption accelerates across enterprise environments, the attack surface expands: unauthenticated tool access, unsigned messages, missing audit trails, and unverified agent identities create systemic risk.
This benchmark establishes security configuration guidance for MCP server deployments. It is organized into six domains covering the critical security surfaces of any MCP implementation.
| Profile | Description |
|---|---|
| Level 1 (L1) | Basic security controls that can be implemented with minimal performance impact and are applicable to all MCP deployments. These address the most common and impactful attack vectors. |
| Level 2 (L2) | Defense-in-depth controls for environments handling sensitive data or operating in regulated industries. May require additional infrastructure (e.g., PKI, SIEM integration). |
Each recommendation follows a standard structure:
- Title -- Short descriptive name with profile level
- Description -- What the control requires
- Rationale -- Why this control matters, with regulatory and threat context
- Audit -- How to verify compliance (commands, checks, inspection procedures)
- Remediation -- How to implement the control
- Impact -- Operational considerations
- Default Value -- Current state in most MCP server implementations
- References -- Standards, frameworks, and specifications
Description
The MCP server MUST require authentication for all incoming connections before processing any tool calls or resource requests. Anonymous access to MCP endpoints allows any client -- legitimate or malicious -- to invoke tools and access data without accountability.
Rationale
The OWASP MCP Security Cheat Sheet covers unauthenticated tool access as a critical risk. Without authentication, an attacker who discovers an MCP endpoint can invoke any registered tool, potentially accessing databases, executing code, or modifying production systems. EU AI Act Article 15 requires AI systems to achieve appropriate levels of accuracy, robustness, and cybersecurity, which presupposes authenticated access. The majority of MCP server implementations today ship with no authentication enabled by default.
Audit
- Attempt to connect to the MCP server without providing any credentials:
curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Content-Type: application/json" \ -d '{"tool": "list_files", "arguments": {"path": "/"}}'
- Verify the server returns HTTP 401 Unauthorized or equivalent error.
- Inspect the MCP server configuration file and confirm an authentication provider is configured:
grep -i "auth" /etc/mcp-server/config.yaml - Review server logs to confirm authentication events are recorded for every connection.
Remediation
- Configure an authentication mechanism in the MCP server configuration. Supported methods include:
- API key authentication (minimum: 256-bit keys)
- OAuth 2.0 / OpenID Connect bearer tokens
- Mutual TLS (mTLS) with client certificates
- Example configuration (YAML):
authentication: required: true method: "bearer_token" token_validation: issuer: "https://idp.example.com" audience: "mcp-server"
- Ensure all transport modes (stdio, HTTP/SSE, Streamable HTTP) enforce authentication. For stdio transport, implement authentication at the process invocation layer.
- Rotate API keys on a regular schedule (minimum quarterly).
Impact
Enabling authentication adds latency for token validation (typically <10ms for local validation, <50ms for remote validation). Requires credential distribution to all legitimate MCP clients.
Default Value
Not configured. Most MCP server implementations accept connections without authentication.
References
- OWASP MCP Security Cheat Sheet, Section 2: Authentication and Authorization
- OWASP MCP Top 10: MCP01 (Token Mismanagement & Secret Exposure), MCP02 (Privilege Escalation via Scope Creep), MCP07 (Insufficient Authentication & Authorization)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 4: Authentication)
- EU AI Act, Article 15: Accuracy, Robustness and Cybersecurity
- CIS Controls v8.1: 6.3 (Require MFA for Externally-Exposed Applications), 6.7 (Centralize Access Control)
Description
The MCP server MUST enforce authorization checks at the individual tool level, ensuring that authenticated clients can only invoke tools they are explicitly permitted to use. A blanket "authenticated means authorized for everything" model is insufficient for production deployments.
Rationale
MCP servers often expose tools with vastly different risk profiles -- from read-only data queries to database mutations and code execution. The OWASP MCP Security Cheat Sheet covers the principle of least privilege for tool access. Without granular access control, a compromised or low-privilege agent can invoke high-risk tools. EU AI Act Article 9 requires risk management systems proportionate to the risk level.
Audit
- Review the MCP server access control configuration:
cat /etc/mcp-server/access-control.yaml
- Verify that each tool or tool group has explicit permission entries:
# Expected: per-tool or per-group ACLs tools: read_database: allowed_roles: ["reader", "admin"] execute_query: allowed_roles: ["admin"]
- Test with a low-privilege credential and attempt to invoke a restricted tool:
curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <low-privilege-token>" \ -d '{"tool": "execute_query", "arguments": {"sql": "DROP TABLE users"}}'
- Confirm the server returns HTTP 403 Forbidden.
Remediation
- Define a role-based or attribute-based access control policy for all registered tools.
- Assign each tool a minimum required permission level:
access_control: default_policy: "deny" roles: reader: tools: ["list_files", "read_file", "search"] writer: tools: ["list_files", "read_file", "search", "write_file"] admin: tools: ["*"]
- Set the default policy to "deny" so that newly registered tools are not automatically accessible.
- Review and update access control policies when new tools are added.
Impact
Requires initial effort to classify tools by risk level and assign permissions. May require changes to client configurations if clients currently rely on unrestricted access.
Default Value
Not configured. MCP servers typically grant full tool access to any connected client.
References
- OWASP MCP Security Cheat Sheet, Section 2: Authentication and Authorization
- OWASP MCP Top 10: MCP01 (Token Mismanagement & Secret Exposure), MCP02 (Privilege Escalation via Scope Creep), MCP07 (Insufficient Authentication & Authorization)
- EU AI Act, Article 9: Risk Management System
- NIST SP 800-53: AC-3 Access Enforcement
- CIS Controls v8.1: 6.8 (Define and Maintain Role-Based Access Control), 3.3 (Configure Data Access Control Lists)
Description
The MCP server SHOULD implement graduated access control, where tools are classified by sensitivity tier and clients must present credentials meeting or exceeding the required verification strength to invoke them. This goes beyond binary allow/deny to support graduated access tiers based on verification strength.
Rationale
Not all agents present equal assurance of identity or intent. A locally running agent with a self-signed certificate presents less assurance than one with a verified organizational identity and a clean behavioral history. The OWASP MCP Security Cheat Sheet covers trust elevation for sensitive operations. EU AI Act Article 14 requires appropriate human-machine interface tools, including graduated oversight based on risk.
Audit
- Inspect the server configuration for access tier definitions:
grep -A 10 "access_tiers" /etc/mcp-server/config.yaml - Verify tools are assigned minimum verification requirements:
# Expected configuration access_tiers: basic: "api_key" standard: "oauth_token" elevated: "mtls_or_signed_identity" critical: "verified_identity_with_attestation" tools: read_public_data: min_tier: "basic" modify_database: min_tier: "elevated" execute_payment: min_tier: "critical"
- Test that a client with insufficient verification strength is denied:
# Agent with basic API key attempting an elevated-tier tool curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <basic-api-key>" \ -d '{"tool": "modify_database", "arguments": {}}' # Expected: 403 with reason "insufficient_verification"
Remediation
- Define access tiers in the server configuration based on verification strength (e.g., basic, standard, elevated, critical).
- Classify every registered tool into a minimum access tier based on its capabilities and potential impact.
- Implement verification strength evaluation that considers:
- Authentication method strength (API key < OAuth < mTLS < verified identity)
- Agent behavioral history (prior invocations, error rates)
- Organizational attestation (signed identity credential from a known issuer)
- Return clear error messages indicating the required verification strength when access is denied.
Impact
Requires an access tier evaluation engine and potentially integration with an external identity or reputation service. May increase latency for first-time agent connections.
Default Value
Not configured. No MCP server implementations currently support graduated access control natively.
References
- OWASP MCP Security Cheat Sheet, Section 2: Trust Boundaries
- OWASP MCP Top 10: MCP01 (Token Mismanagement & Secret Exposure), MCP02 (Privilege Escalation via Scope Creep), MCP07 (Insufficient Authentication & Authorization)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 5: Trust Model)
- EU AI Act, Article 14: Human Oversight
- CIS Controls v8.1 Gap: No existing control addresses graduated access based on agent verification strength. Nearest: 6.8 (RBAC), but RBAC does not model graduated trust tiers tied to cryptographic verification strength. This is an MCP-specific risk requiring new control guidance.
Description
For tools classified as sensitive (e.g., those with financial, data-destructive, or privacy-impacting capabilities), the MCP server MUST require cryptographic agent identity verification beyond standard authentication. This means verifying a signed agent identity assertion or equivalent cryptographic identity credential before granting access.
Rationale
API keys and bearer tokens establish session identity but do not cryptographically bind a specific agent to an action. The OWASP MCP Security Cheat Sheet covers the risk of credential sharing and delegation attacks. For tools that trigger payments, modify sensitive data, or access personal information, operators need non-repudiable proof of which agent acted. EU AI Act Article 12 requires traceability of AI system operations.
Audit
- Identify tools classified as sensitive in the server configuration:
grep -B 2 "requires_identity: true" /etc/mcp-server/tools.yaml - Attempt to invoke a sensitive tool with a valid bearer token but without an agent identity assertion:
curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <valid-token>" \ -d '{"tool": "transfer_funds", "arguments": {"amount": 1000}}' # Expected: 403 with reason "agent_identity_required"
- Verify the server validates the cryptographic signature on agent identity assertions:
# Check server logs for signature verification events grep "agent_identity_verified" /var/log/mcp-server/audit.log
Remediation
- Tag sensitive tools with
requires_identity: truein the tool registry. - Implement an agent identity verification handler that:
- Accepts a signed identity assertion (JWT, JWS, or equivalent) in the request headers
- Validates the signature against known issuer public keys
- Checks expiration, audience, and scope claims
- Logs the verified agent identity alongside the tool call
- Example header:
X-Agent-Identity: eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9... - Maintain a registry of trusted agent identity issuers and their public keys.
Impact
Requires agents to obtain and present signed identity assertions. Adds overhead for identity verification (~10-50ms per call). Requires PKI infrastructure or integration with an agent identity provider.
Default Value
Not configured. No MCP server implementations require agent identity verification.
References
- OWASP MCP Security Cheat Sheet, Section 3: Agent Identity
- OWASP MCP Top 10: MCP01 (Token Mismanagement & Secret Exposure), MCP02 (Privilege Escalation via Scope Creep), MCP07 (Insufficient Authentication & Authorization)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 6: Agent Identity)
- IETF Internet-Draft: draft-sharif-openid-agent-identity
- EU AI Act, Article 12: Record-Keeping and Traceability
- CIS Controls v8.1 Gap: No existing control addresses cryptographic identity verification for autonomous AI agents. Nearest: 6.3 (MFA for externally-exposed applications), but MFA is designed for human authentication, not autonomous agent identity binding. This is an MCP-specific risk requiring new control guidance.
Description
The MCP server MUST sign all outgoing messages (tool results, resource responses, notifications) and SHOULD require clients to sign all incoming messages (tool calls, resource requests). Per-message signing provides integrity verification and non-repudiation for every interaction.
Rationale
TLS protects data in transit but does not provide end-to-end integrity once the message is decrypted. Without message-level signing, a compromised proxy, logging system, or intermediary can modify tool call arguments or results without detection. The OWASP MCP Security Cheat Sheet covers message tampering as a key risk. The IETF MCP Security draft specifies per-message signing as a core requirement.
Audit
- Inspect the server configuration for message signing settings:
grep -A 5 "message_signing" /etc/mcp-server/config.yaml - Make a tool call and inspect the response for a signature header or field:
curl -v -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -d '{"tool": "get_status", "arguments": {}}' 2>&1 | grep -i "signature" # Expected: X-Message-Signature header or "signature" field in response body
- Verify the signature is valid using the server's public key:
# Extract the signature and verify against the response body openssl dgst -sha256 -verify server-public.pem -signature sig.bin response.json
Remediation
- Enable message signing in the server configuration:
message_signing: enabled: true algorithm: "ES256" # ECDSA with P-256 and SHA-256 key_id: "mcp-server-signing-key-2026" include_headers: ["X-Message-Signature", "X-Signature-Input"]
- Generate an ECDSA P-256 signing key pair:
openssl ecparam -name prime256v1 -genkey -noout -out private.pem openssl ec -in private.pem -pubout -out public.pem
- Publish the server's public key at a well-known endpoint:
GET /.well-known/mcp-signing-keys - For HTTP transport, use HTTP Message Signatures (RFC 9421) for standards-compliant signing.
Impact
Adds computational overhead for signing each message (~1-5ms for ECDSA P-256). Increases response size by approximately 100-200 bytes per message for the signature. Requires key management infrastructure.
Default Value
Not configured. No MCP server implementations sign messages by default.
References
- OWASP MCP Security Cheat Sheet, Section 4: Message Integrity
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP06 (Intent Flow Subversion)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 7: Message Signing)
- RFC 9421: HTTP Message Signatures
- RFC 7515: JSON Web Signature (JWS)
- CIS Controls v8.1 Gap: No existing control addresses application-layer per-message signing. CIS 3.10 (Encrypt Sensitive Data in Transit) covers transport encryption but not application-layer message integrity and non-repudiation. This is an MCP-specific risk requiring new control guidance.
Description
The MCP server MUST implement replay protection to prevent previously captured valid messages from being resubmitted. This requires tracking message identifiers and timestamps to reject duplicate or stale requests.
Rationale
Without replay protection, an attacker who captures a signed, authenticated tool call can resubmit it indefinitely. This is particularly dangerous for tools with side effects: a captured payment tool call could be replayed to drain funds. The OWASP MCP Security Cheat Sheet covers replay attacks on MCP connections. The risk is amplified in environments where messages pass through logging proxies or message queues.
Audit
- Check the server configuration for replay protection settings:
grep -A 5 "replay_protection" /etc/mcp-server/config.yaml - Send a tool call and capture the response:
RESPONSE=$(curl -s -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -H "X-Request-Id: unique-id-12345" \ -H "X-Timestamp: 2026-03-29T12:00:00Z" \ -d '{"tool": "get_status", "arguments": {}}')
- Replay the exact same request:
curl -s -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -H "X-Request-Id: unique-id-12345" \ -H "X-Timestamp: 2026-03-29T12:00:00Z" \ -d '{"tool": "get_status", "arguments": {}}' | jq .error # Expected: "replay_detected" or HTTP 409 Conflict
- Send a request with an expired timestamp (>5 minutes old) and verify rejection.
Remediation
- Enable replay protection in the server configuration:
replay_protection: enabled: true window_seconds: 300 # 5-minute window nonce_tracking: true storage: "memory" # or "redis" for distributed deployments
- Require clients to include a unique nonce and timestamp in every request.
- Track seen nonces within the validity window and reject duplicates.
- Reject requests with timestamps outside the configured validity window.
- For distributed deployments, use a shared nonce store (e.g., Redis with TTL matching the window).
Impact
Requires server-side nonce tracking, consuming memory proportional to request volume within the replay window. For high-throughput servers, a shared store (Redis) is recommended. Clock skew between clients and servers must be accounted for.
Default Value
Not configured. MCP servers do not implement replay protection by default.
References
- OWASP MCP Security Cheat Sheet, Section 4: Message Integrity
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP06 (Intent Flow Subversion)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 7.2: Replay Protection)
- RFC 7616: HTTP Digest Access Authentication (nonce mechanism)
- CIS Controls v8.1 Gap: No existing control addresses application-layer replay attacks. CIS controls cover network-layer protections but not protocol-level nonce and timestamp enforcement for tool invocations. This is an MCP-specific risk requiring new control guidance.
Description
The MCP server MUST sign tool definitions (the schema that describes available tools, their parameters, and descriptions) so that clients can verify the definitions have not been tampered with. Tool definitions are the "contract" between client and server, and unsigned definitions are vulnerable to tool poisoning attacks.
Rationale
Tool poisoning -- where an attacker modifies tool descriptions to manipulate LLM behavior -- is a well-documented MCP attack vector. The OWASP MCP Security Cheat Sheet covers tool description injection as a critical risk. By signing tool definitions, the server provides cryptographic assurance that the tool schema is authentic and has not been modified by an intermediary. EU AI Act Article 15(4) requires resilience against unauthorized third-party manipulation.
Audit
- Request the tool list and check for a signature:
curl -s https://<mcp-server>/mcp/v1/tools/list \ -H "Authorization: Bearer <token>" | jq '.signature' # Expected: non-null signature value
- Verify the signature covers the complete tool definitions:
# Extract definitions and signature, verify independently curl -s https://<mcp-server>/mcp/v1/tools/list \ -H "Authorization: Bearer <token>" > tools.json jq '.tools' tools.json > definitions.json jq -r '.signature' tools.json | base64 -d > sig.bin openssl dgst -sha256 -verify server-public.pem -signature sig.bin definitions.json
- Confirm the signature changes when tool definitions are updated.
Remediation
- Enable tool definition signing in the server configuration:
tool_signing: enabled: true algorithm: "ES256" include_fields: ["name", "description", "inputSchema", "annotations"]
- Sign the complete tool definition array each time
tools/listis called. - Include a
definitionsHashfield in the response for quick integrity checks. - Publish the signing public key via
/.well-known/mcp-signing-keys. - When tool definitions change, generate a new signature and increment a version counter.
Impact
Adds signing overhead to tools/list responses. Clients must implement signature verification logic. Changing tool definitions requires re-signing, which must be integrated into the deployment pipeline.
Default Value
Not configured. Tool definitions are served unsigned in all current MCP implementations.
References
- OWASP MCP Security Cheat Sheet, Section 5: Tool Poisoning
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP06 (Intent Flow Subversion)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 8: Tool Definition Integrity)
- EU AI Act, Article 15(4): Resilience Against Manipulation
- CIS Controls v8.1 Gap: No existing control addresses cryptographic signing of dynamic tool definitions. Nearest: 2.5 (Allowlist Authorized Software), but software allowlisting does not cover dynamically served tool schemas that can be poisoned at runtime. This is an MCP-specific risk requiring new control guidance.
Description
When signing JSON messages or tool definitions, the MCP server MUST use JSON Canonicalization Scheme (JCS, RFC 8785) to produce a deterministic byte representation before signing. Without canonical serialization, equivalent JSON objects can produce different byte sequences, leading to signature verification failures or exploitable ambiguity.
Rationale
JSON allows multiple valid representations of the same data (varying whitespace, key ordering, Unicode escaping). If a server signs one representation and a client verifies against another, legitimate messages may fail verification. Conversely, an attacker could exploit serialization ambiguity to create messages that pass verification but are interpreted differently. The IETF MCP Security draft specifies RFC 8785 as the required canonicalization method.
Audit
- Request a signed response from the server and inspect the serialization:
curl -s https://<mcp-server>/mcp/v1/tools/list \ -H "Authorization: Bearer <token>" > response.json
- Verify the signed payload uses RFC 8785 canonical form:
- Keys are sorted lexicographically
- No unnecessary whitespace
- Numbers use shortest representation
- Unicode escapes use lowercase hex
- Canonicalize the payload independently and verify the signature matches:
# Using a JCS library to canonicalize node -e "const jcs = require('canonicalize'); \ const data = require('./response.json').tools; \ process.stdout.write(jcs(data));" > canonical.json openssl dgst -sha256 -verify server-public.pem -signature sig.bin canonical.json
Remediation
- Integrate an RFC 8785 (JCS) library into the MCP server:
- Node.js:
npm install canonicalize - Python:
pip install json-canonicalization - Go:
go get github.com/nicktrav/jcs
- Node.js:
- Canonicalize all JSON payloads before signing:
const canonicalize = require('canonicalize'); const payload = canonicalize(toolDefinitions); const signature = sign(payload, privateKey);
- Document the canonicalization requirement in the server's API specification.
- Include a
canonicalizationfield in signed responses to indicate the method used:{ "canonicalization": "RFC8785" }
Impact
Minimal performance impact (canonicalization is fast). Requires all signing and verification implementations to use the same canonicalization library. May require updates to existing client implementations.
Default Value
Not configured. No MCP implementations currently use canonical serialization for signing.
References
- RFC 8785: JSON Canonicalization Scheme (JCS)
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP06 (Intent Flow Subversion)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 7.1: Canonical Serialization)
- RFC 7515: JSON Web Signature (JWS)
- CIS Controls v8.1 Gap: No existing control addresses canonical serialization requirements for cryptographic signing. This is an implementation-level requirement specific to JSON-based protocol signing with no CIS equivalent. This is an MCP-specific risk requiring new control guidance.
Description
The MCP server MUST log every tool invocation with, at minimum: timestamp (ISO 8601 with timezone), agent or client identifier, tool name, a summary of arguments (redacting sensitive values), and the outcome (success, error, or denied). This log forms the basis for incident investigation, compliance reporting, and behavioral analysis.
Rationale
Without comprehensive tool call logging, operators cannot determine which agent invoked which tool, when, or with what arguments. This makes incident response impossible and violates EU AI Act Article 12, which requires automatic recording of events ("logs") throughout the AI system's lifecycle. The OWASP MCP Security Cheat Sheet covers logging requirements for MCP deployments.
Audit
- Invoke a tool and inspect the server's audit log:
curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -d '{"tool": "read_file", "arguments": {"path": "/tmp/test.txt"}}'
- Check the audit log for the corresponding entry:
tail -5 /var/log/mcp-server/audit.log | jq .
- Verify the log entry contains required fields:
{ "timestamp": "2026-03-29T12:00:00.000Z", "agent_id": "agent-abc123", "tool": "read_file", "arguments_hash": "sha256:a1b2c3...", "outcome": "success", "duration_ms": 45 } - Verify that sensitive argument values (passwords, tokens, PII) are redacted or hashed, not logged in cleartext.
Remediation
- Enable audit logging in the server configuration:
audit: enabled: true log_path: "/var/log/mcp-server/audit.log" format: "json" fields: - timestamp - agent_id - tool_name - arguments_hash - outcome - duration_ms - request_id redact_patterns: - "password" - "token" - "secret" - "api_key"
- Use structured JSON logging for machine-parseable output.
- Include a unique
request_idfor correlation across distributed systems. - Hash or redact argument values that may contain sensitive data.
Impact
Logging adds I/O overhead per tool call. For high-throughput servers, use asynchronous log writing or a buffered logging pipeline. Log storage requirements scale linearly with tool call volume.
Default Value
Not configured. Most MCP server implementations provide minimal or no audit logging.
References
- OWASP MCP Security Cheat Sheet, Section 6: Logging and Monitoring
- OWASP MCP Top 10: MCP08 (Lack of Audit and Telemetry)
- EU AI Act, Article 12: Record-Keeping
- NIST SP 800-92: Guide to Computer Security Log Management
- CIS Controls v8.1: 8.2 (Collect Audit Logs), 8.5 (Collect Detailed Audit Logs)
Description
The MCP server SHOULD produce tamper-evident audit logs, where each log entry is chained or signed such that any modification, insertion, or deletion of entries is detectable. This provides assurance that the audit trail accurately reflects what occurred on the server.
Rationale
Standard log files can be silently modified by an attacker who gains server access, destroying evidence of their actions. For regulatory compliance (EU AI Act Article 12) and forensic integrity, logs must be tamper-evident. The OWASP MCP Security Cheat Sheet covers the integrity of audit records as a defense-in-depth measure.
Audit
- Inspect the audit log for integrity markers:
head -3 /var/log/mcp-server/audit.log | jq '.chain_hash' # Expected: each entry contains a hash chaining to the previous entry
- Verify the hash chain:
# Programmatically verify: hash(entry[n-1]) == entry[n].previous_hash python3 -c " import json, hashlib with open('/var/log/mcp-server/audit.log') as f: entries = [json.loads(line) for line in f] for i in range(1, len(entries)): expected = hashlib.sha256(json.dumps(entries[i-1]).encode()).hexdigest() assert entries[i]['previous_hash'] == expected, f'Chain broken at entry {i}' print('Hash chain valid') "
- Optionally verify that log entries are periodically signed by a separate key:
grep "log_checkpoint" /var/log/mcp-server/audit.log | tail -1 | jq '.signature'
Remediation
- Enable hash-chained logging:
audit: tamper_evident: true chain_algorithm: "SHA-256" checkpoint_interval: 1000 # Sign a checkpoint every 1000 entries checkpoint_key: "/etc/mcp-server/log-signing-key.pem"
- Each log entry includes a
previous_hashfield containing the SHA-256 hash of the preceding entry. - Periodically insert signed checkpoint entries using a key stored separately from the server's runtime keys.
- For high-assurance environments, forward logs to a write-once store (e.g., Amazon S3 Object Lock, immutable Azure Blob) in near-real-time.
Impact
Hash chaining adds minimal computational overhead (~microseconds per entry). Checkpoint signing adds periodic overhead. Write-once storage may increase costs.
Default Value
Not configured. Audit logs in MCP servers are standard append-only text files with no integrity protection.
References
- OWASP MCP Security Cheat Sheet, Section 6: Logging and Monitoring
- OWASP MCP Top 10: MCP08 (Lack of Audit and Telemetry)
- EU AI Act, Article 12(2): Logs shall be kept for an appropriate period of time
- NIST SP 800-92: Guide to Computer Security Log Management
- RFC 9162: Certificate Transparency (hash chain model)
- CIS Controls v8.1: 8.9 (Centralize Audit Logs) -- partial mapping. CIS addresses log centralization but not cryptographic tamper-evidence (hash chaining or signed checkpoints).
Description
The MCP server MUST retain audit logs for a period that meets or exceeds applicable regulatory requirements. The retention period must be documented and enforced through automated log rotation and archival policies.
Rationale
Different regulatory frameworks mandate different retention periods. EU AI Act Article 12(2) requires logs to be "kept for a period that is appropriate in view of the intended purpose." GDPR requires sufficient records to demonstrate compliance. Financial regulations (PCI DSS, SOX) may require 1-7 years. Without a defined retention policy, logs may be prematurely deleted, destroying evidence needed for compliance audits or incident investigations.
Audit
- Check the log rotation configuration:
cat /etc/logrotate.d/mcp-server
- Verify the retention period meets requirements:
# Check oldest available log entry head -1 /var/log/mcp-server/audit.log.1 | jq '.timestamp' # Verify archived logs exist for the required retention period ls -la /var/log/mcp-server/archive/
- Confirm the documented retention policy:
grep "retention" /etc/mcp-server/config.yaml # Expected: retention_days >= regulatory minimum
Remediation
- Define a retention policy based on applicable regulations:
audit: retention: active_days: 90 # Keep in primary storage archive_days: 2555 # 7 years in archive (PCI DSS / SOX) archive_storage: "s3://mcp-audit-archive/" compression: "gzip"
- Configure log rotation:
# /etc/logrotate.d/mcp-server /var/log/mcp-server/audit.log { daily rotate 90 compress dateext postrotate /usr/bin/mcp-archive-logs endscript } - Document the retention policy and map it to specific regulatory requirements.
- Set up alerting if log archival fails.
Impact
Long-term log retention increases storage costs. Compressed JSON logs typically consume 50-200 bytes per tool call. For a server handling 10,000 calls/day, this equates to approximately 500KB-2MB per day before compression.
Default Value
Not configured. No retention policy is defined in default MCP server installations.
References
- OWASP MCP Top 10: MCP08 (Lack of Audit and Telemetry)
- EU AI Act, Article 12(2): Record-Keeping Duration
- PCI DSS v4.0.1, Requirement 10.7: Retain audit trail history for at least 12 months
- NIST SP 800-92: Guide to Computer Security Log Management
- CIS Controls v8.1: 8.10 (Retain Audit Logs)
Description
The MCP server SHOULD support exporting audit logs to a Security Information and Event Management (SIEM) system in a standard format (e.g., CEF, LEEF, JSON over Syslog, or OCSF). This enables centralized monitoring, correlation with other security events, and automated alerting.
Rationale
Isolated MCP audit logs provide limited value for security operations. Integrating with a SIEM enables correlation of MCP tool calls with network events, authentication logs, and threat intelligence. The OWASP MCP Security Cheat Sheet covers the importance of centralized monitoring for MCP deployments. Organizations with SOC teams need MCP events in their existing monitoring workflows.
Audit
- Check the server configuration for SIEM integration:
grep -A 10 "siem" /etc/mcp-server/config.yaml - Verify log export is functioning:
# Check syslog forwarding logger -t mcp-test "test message" && \ ssh siem-server "grep 'mcp-test' /var/log/syslog"
- Verify the log format is parseable by the SIEM:
# Check for structured format (CEF, JSON, OCSF) tail -1 /var/log/mcp-server/audit.log | python3 -m json.tool
- Confirm that SIEM alerts are configured for critical MCP events (authentication failures, denied tool calls, anomalous invocation patterns).
Remediation
- Configure SIEM export in the server:
audit: siem: enabled: true transport: "syslog" # or "http", "kafka" endpoint: "siem.internal:514" format: "json" # or "cef", "ocsf" tls: true buffer_size: 1000 flush_interval_seconds: 5
- Map MCP audit fields to the SIEM's expected schema:
MCP Field CEF Field OCSF Field timestamp rt time agent_id suser actor.user.uid tool_name cs1 api.operation outcome outcome status - Create SIEM detection rules for:
- Repeated authentication failures from the same agent
- Tool calls outside normal operating hours
- Invocation of high-risk tools by new agents
- Abnormal tool call volume spikes
Impact
SIEM integration requires network connectivity to the SIEM endpoint. Buffered export minimizes latency impact. SIEM licensing costs may increase based on log volume.
Default Value
Not configured. MCP servers log to local files only, with no SIEM integration.
References
- OWASP MCP Security Cheat Sheet, Section 6: Logging and Monitoring
- OWASP MCP Top 10: MCP08 (Lack of Audit and Telemetry)
- OCSF (Open Cybersecurity Schema Framework): schema.ocsf.io
- RFC 5424: The Syslog Protocol
- CIS Controls v8.1: 8.9 (Centralize Audit Logs), 8.11 (Conduct Audit Log Reviews)
Description
The MCP server MUST require TLS 1.2 or higher for all HTTP-based transport modes (HTTP/SSE and Streamable HTTP). TLS 1.0 and 1.1 MUST be disabled. The server SHOULD prefer TLS 1.3 where supported.
Rationale
TLS 1.0 and 1.1 contain known vulnerabilities (BEAST, POODLE, Lucky13) that allow traffic decryption under certain conditions. The OWASP MCP Security Cheat Sheet covers transport security requirements. PCI DSS v4.0.1 mandates TLS 1.2+ for all cardholder data transmission. MCP tool calls frequently contain sensitive arguments and responses that must be protected in transit.
Audit
- Test the server's TLS configuration:
# Check minimum TLS version openssl s_client -connect <mcp-server>:443 -tls1_1 2>&1 | grep -i "alert\|error" # Expected: connection failure for TLS 1.1 openssl s_client -connect <mcp-server>:443 -tls1_2 2>&1 | grep "Protocol" # Expected: "Protocol : TLSv1.2" or "Protocol : TLSv1.3"
- Scan with a TLS testing tool:
nmap --script ssl-enum-ciphers -p 443 <mcp-server> # Verify: no TLS 1.0 or 1.1 support, no weak ciphers
- Verify certificate validity:
echo | openssl s_client -connect <mcp-server>:443 2>/dev/null | \ openssl x509 -noout -dates -subject
Remediation
- Configure the web server or reverse proxy to enforce TLS 1.2+:
# nginx example ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on;
- If the MCP server handles TLS directly:
tls: min_version: "1.2" preferred_version: "1.3" certificate: "/etc/mcp-server/cert.pem" key: "/etc/mcp-server/key.pem" ciphers: - "TLS_AES_256_GCM_SHA384" - "TLS_CHACHA20_POLY1305_SHA256" - "TLS_AES_128_GCM_SHA256"
- Enable HSTS to prevent protocol downgrade:
Strict-Transport-Security: max-age=31536000; includeSubDomains - Use automated certificate management (e.g., Let's Encrypt with auto-renewal).
Impact
TLS 1.2+ is supported by all modern clients and operating systems. Dropping TLS 1.0/1.1 may affect legacy systems (pre-2014), which should not be connecting to MCP servers. TLS 1.3 reduces handshake latency by one round-trip.
Default Value
Varies. Many MCP servers rely on the underlying runtime's default TLS settings. Node.js 18+ defaults to TLS 1.2 minimum. Python's ssl module defaults vary by version.
References
- OWASP MCP Security Cheat Sheet, Section 7: Transport Security
- OWASP MCP Top 10: MCP05 (Command Injection & Execution), MCP09 (Shadow MCP Servers)
- PCI DSS v4.0.1, Requirement 4.2: Strong Cryptography for Transmission
- RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
- NIST SP 800-52 Rev. 2: Guidelines for TLS Implementations
- CIS Controls v8.1: 3.10 (Encrypt Sensitive Data in Transit)
Description
The MCP server MUST implement rate limiting to prevent denial-of-service attacks and resource exhaustion from individual clients. Rate limits SHOULD be configurable per-agent, per-tool, and globally.
Rationale
An MCP server without rate limiting is vulnerable to resource exhaustion from a single misbehaving or compromised agent that floods tool calls. This can degrade service for all clients and potentially exhaust backend resources (database connections, API quotas, compute). The OWASP MCP Security Cheat Sheet covers denial-of-service risks for MCP servers.
Audit
- Check the server configuration for rate limiting:
grep -A 10 "rate_limit" /etc/mcp-server/config.yaml - Test rate limiting by sending rapid requests:
for i in $(seq 1 100); do curl -s -o /dev/null -w "%{http_code}\n" \ -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -d '{"tool": "get_status", "arguments": {}}' done | sort | uniq -c # Expected: HTTP 429 responses after limit is reached
- Verify rate limit headers in responses:
curl -v https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -d '{"tool": "get_status", "arguments": {}}' 2>&1 | \ grep -i "ratelimit\|retry-after" # Expected: X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After headers
Remediation
- Configure rate limits in the server:
rate_limiting: enabled: true global: requests_per_minute: 1000 per_agent: requests_per_minute: 100 per_tool: high_risk: requests_per_minute: 10 default: requests_per_minute: 60 response_headers: true exceeded_status: 429
- Implement tiered rate limits based on tool sensitivity:
- Read-only tools: higher limits
- Write/mutation tools: lower limits
- Financial/destructive tools: strict limits
- Return standard rate limit headers:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 45 X-RateLimit-Reset: 1711713600 Retry-After: 30 - Log rate limit violations for security monitoring.
Impact
Rate limiting may affect legitimate high-throughput agent workflows. Set limits based on observed traffic patterns with a reasonable margin. Implement graceful degradation (queuing) rather than hard rejection where appropriate.
Default Value
Not configured. MCP servers do not implement rate limiting by default.
References
- OWASP MCP Security Cheat Sheet, Section 7: Denial of Service Prevention
- OWASP MCP Top 10: MCP05 (Command Injection & Execution), MCP09 (Shadow MCP Servers)
- RFC 6585: Additional HTTP Status Codes (429 Too Many Requests)
- IETF Internet-Draft: draft-ietf-httpapi-ratelimit-headers
- CIS Controls v8.1: 13.3 (Deploy a Network Intrusion Prevention Solution) -- partial mapping. Network IPS operates at the network layer; MCP rate limiting requires application-layer, per-agent, per-tool throttling not covered by existing controls.
Description
The MCP server MUST NOT include implementation details in error responses returned to clients. Stack traces, file paths, database query fragments, library versions, and internal hostnames MUST be stripped from all error responses.
Rationale
Detailed error messages are invaluable for developers but equally valuable for attackers performing reconnaissance. The OWASP MCP Security Cheat Sheet covers information disclosure through error responses. A stack trace revealing the server framework (e.g., "Express 4.18.2") or database (e.g., "PostgreSQL 15.4") enables targeted exploitation. EU AI Act Article 15 requires cybersecurity measures proportionate to the risk.
Audit
- Send a malformed request and inspect the error response:
curl -s -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -d '{"tool": "nonexistent_tool"}' | jq . # Verify: no stack trace, file paths, or version numbers
- Send an invalid argument type to trigger a validation error:
curl -s -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -d '{"tool": "read_file", "arguments": {"path": 12345}}' | jq . # Verify: generic error message, no internal details
- Check for information leakage in HTTP headers:
curl -sI https://<mcp-server>/ | grep -iE "server|x-powered|x-aspnet|x-runtime" # Expected: no version-identifying headers
Remediation
- Implement an error sanitization layer:
error_handling: sanitize_responses: true expose_stack_traces: false expose_internal_errors: false generic_message: "An internal error occurred. Reference ID: {request_id}"
- Map internal errors to generic external error codes:
{ "error": { "code": "TOOL_EXECUTION_ERROR", "message": "The tool encountered an error during execution.", "reference_id": "req-abc123" } } - Log full error details (including stack traces) server-side for debugging.
- Remove version-identifying HTTP headers:
server_tokens off; proxy_hide_header X-Powered-By;
- Use the reference ID to correlate client-reported errors with server-side logs.
Impact
Developers lose direct visibility into error causes from client-side responses. Provide a reference ID in error responses and a mechanism (e.g., admin dashboard or log search) to look up full error details server-side.
Default Value
Not hardened. Most MCP server frameworks return detailed error messages including stack traces in development mode, and many deployments do not switch to production error handling.
References
- OWASP MCP Security Cheat Sheet, Section 7: Error Handling
- OWASP MCP Top 10: MCP05 (Command Injection & Execution), MCP09 (Shadow MCP Servers)
- OWASP Testing Guide: OTG-ERR-001 (Error Handling)
- CWE-209: Generation of Error Message Containing Sensitive Information
- EU AI Act, Article 15: Accuracy, Robustness and Cybersecurity
- CIS Controls v8.1: 16.1 (Establish and Maintain a Secure Application Development Process) -- partial mapping. Secure development practices include error handling, but CIS does not specifically address MCP-context information leakage through tool error responses.
Description
The MCP server operator MUST maintain a complete inventory of all registered tools, including their name, version, description, input schema, capabilities (filesystem access, network access, code execution, data mutation), and owner/maintainer. This inventory must be reviewed periodically.
Rationale
You cannot secure what you do not know exists. The OWASP MCP Security Cheat Sheet covers tool inventory as a foundational requirement for MCP security. Without an inventory, operators cannot assess the attack surface, enforce access controls, or detect unauthorized tool additions. EU AI Act Article 9 requires risk management that identifies and analyzes known and reasonably foreseeable risks.
Audit
- Request the tool list from the server and compare against the documented inventory:
curl -s https://<mcp-server>/mcp/v1/tools/list \ -H "Authorization: Bearer <token>" | jq '[.tools[].name]' > live_tools.json diff <(jq -S . live_tools.json) <(jq -S . /etc/mcp-server/tool-inventory.json) # Expected: no differences
- Check that each tool in the inventory has required metadata:
jq '.[] | select(.owner == null or .capabilities == null)' \ /etc/mcp-server/tool-inventory.json # Expected: empty result (all tools have owner and capabilities)
- Verify the inventory was reviewed within the last 90 days:
grep "last_reviewed" /etc/mcp-server/tool-inventory.json | head -1
Remediation
- Create a tool inventory file:
{ "last_reviewed": "2026-03-29", "reviewer": "security-team@example.com", "tools": [ { "name": "read_file", "version": "1.0.0", "description": "Reads a file from the filesystem", "owner": "platform-team", "capabilities": ["filesystem_read"], "risk_level": "medium", "approved": true, "approved_date": "2026-03-01" } ] } - Implement an automated check that compares the live tool list against the inventory on startup and on a schedule.
- Alert when tools appear in the live list but not in the inventory (unexpected tool registration).
- Review the inventory quarterly or when tools are added, removed, or modified.
Impact
Requires initial effort to document all tools. Ongoing maintenance required as tools change. Automated comparison reduces manual overhead.
Default Value
Not configured. MCP servers do not maintain or enforce a tool inventory.
References
- OWASP MCP Security Cheat Sheet, Section 5: Tool Supply Chain
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP04 (Supply Chain Attacks & Dependency Tampering)
- EU AI Act, Article 9: Risk Management System
- NIST SP 800-53: CM-8 Information System Component Inventory
- CIS Controls v8.1: 2.1 (Establish and Maintain a Software Inventory)
Description
Tools that expose dangerous capabilities -- including arbitrary code execution, filesystem write access, network access to internal services, database mutation, or financial operations -- MUST have documented justification for their inclusion. The justification must include the business need, alternative approaches considered, and compensating controls.
Rationale
MCP tool registrations are often developer-driven with no security review. The OWASP MCP Security Cheat Sheet covers the risk of over-permissive tool capabilities. A tool registered for convenience (e.g., "execute arbitrary SQL") may expose the entire database without the operator's awareness. EU AI Act Article 9(2)(b) requires identification of risks that may emerge from the interaction with other AI systems.
Audit
- Identify tools with dangerous capabilities in the inventory:
jq '.tools[] | select(.capabilities[] | IN("code_execution","filesystem_write","database_mutation","network_internal","financial"))' \ /etc/mcp-server/tool-inventory.json
- Verify each dangerous tool has a documented justification:
jq '.tools[] | select(.risk_level == "high" or .risk_level == "critical") | select(.justification == null)' /etc/mcp-server/tool-inventory.json # Expected: empty result
- Review that compensating controls are listed and active for each dangerous tool.
Remediation
- For each tool with dangerous capabilities, document:
{ "name": "execute_query", "capabilities": ["database_mutation"], "risk_level": "critical", "justification": { "business_need": "Required for automated data migration workflows", "alternatives_considered": [ "Pre-built parameterized queries (rejected: insufficient flexibility)" ], "compensating_controls": [ "Per-tool access control (admin role only)", "Query allow-list (only SELECT, INSERT, UPDATE on approved tables)", "All invocations logged with full query text", "Agent identity verification required" ], "approved_by": "ciso@example.com", "review_date": "2026-03-01", "next_review": "2026-06-01" } } - Implement a review process that requires security sign-off for dangerous tools.
- Consider wrapping dangerous tools with guardrails (input validation, allow-lists, confirmation prompts) rather than exposing raw capabilities.
Impact
Requires security review overhead for dangerous tools. May slow the pace of tool registration. This is an intentional friction that prevents unreviewed dangerous capabilities from entering production.
Default Value
Not configured. No MCP implementations require justification for tool capabilities.
References
- OWASP MCP Security Cheat Sheet, Section 5: Tool Supply Chain
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP04 (Supply Chain Attacks & Dependency Tampering)
- EU AI Act, Article 9(2)(b): Identification and Analysis of Risks
- CWE-250: Execution with Unnecessary Privileges
- CIS Controls v8.1: 2.5 (Allowlist Authorized Software)
Description
The MCP server SHOULD monitor tool definitions for changes and trigger alerts when tools are added, removed, or modified. This detects both unauthorized tool injection and subtle modifications to existing tool descriptions or schemas.
Rationale
Tool poisoning attacks often involve modifying tool descriptions to inject instructions that manipulate LLM behavior, or altering input schemas to exfiltrate data through unexpected parameters. The OWASP MCP Security Cheat Sheet covers tool definition mutation as an attack vector. Without change detection, these modifications can persist undetected. This is analogous to file integrity monitoring (FIM) for traditional systems.
Audit
- Check for tool definition monitoring configuration:
grep -A 5 "tool_monitoring" /etc/mcp-server/config.yaml - Simulate a tool definition change and verify an alert is generated:
# Record current tool definitions hash curl -s https://<mcp-server>/mcp/v1/tools/list | sha256sum # Modify a tool definition (in a test environment) # Verify alert appears in monitoring system within SLA
- Review alert history for tool definition change events:
grep "tool_definition_changed" /var/log/mcp-server/alerts.log
Remediation
- Enable tool definition monitoring:
tool_monitoring: enabled: true check_interval_seconds: 60 alert_on: - tool_added - tool_removed - tool_description_changed - tool_schema_changed alert_channels: - type: "webhook" url: "https://alerts.example.com/mcp" - type: "email" to: "security@example.com" baseline_file: "/etc/mcp-server/tool-baseline.json"
- Generate a baseline of tool definitions on deployment:
curl -s https://<mcp-server>/mcp/v1/tools/list | \ jq '.tools' > /etc/mcp-server/tool-baseline.json
- Compare the live tool list against the baseline on each check interval.
- Integrate alerts with the SIEM for correlation (see Control 3.4).
Impact
Monitoring adds a periodic check (typically once per minute). Alert fatigue is possible if tool definitions change frequently during development; consider separate monitoring profiles for development and production.
Default Value
Not configured. No MCP implementations monitor tool definitions for changes.
References
- OWASP MCP Security Cheat Sheet, Section 5: Tool Poisoning
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP04 (Supply Chain Attacks & Dependency Tampering)
- NIST SP 800-53: SI-7 Software, Firmware, and Information Integrity
- CIS Controls v8.1 Gap: No existing control addresses runtime monitoring of dynamic tool definition changes. Nearest: 2.7 (Allowlist Authorized Libraries), but MCP tool definitions are not libraries -- they are dynamically served schemas that can be poisoned without modifying any installed software. This is an MCP-specific risk requiring new control guidance.
Description
All software dependencies of the MCP server (runtime libraries, MCP SDK, tool implementation packages) MUST be regularly scanned for known vulnerabilities. Critical and high-severity vulnerabilities MUST be remediated within defined SLA timelines.
Rationale
MCP servers depend on SDK libraries, web frameworks, and tool-specific packages that may contain known vulnerabilities. The OWASP MCP Security Cheat Sheet covers supply chain risks in MCP deployments. A vulnerability in the MCP SDK or a tool's dependency directly impacts the security of all tool invocations. EU AI Act Article 15 requires cybersecurity measures throughout the AI system's lifecycle.
Audit
- Run a vulnerability scan on the MCP server's dependencies:
# Node.js cd /opt/mcp-server && npm audit --json | jq '.metadata.vulnerabilities' # Python cd /opt/mcp-server && pip-audit --format json # General (using Trivy) trivy fs --severity HIGH,CRITICAL /opt/mcp-server/
- Verify that no critical or high-severity vulnerabilities are present:
npm audit --audit-level=high # Expected: "found 0 vulnerabilities" - Check that dependency scanning is integrated into the CI/CD pipeline:
grep -r "audit\|trivy\|snyk\|grype" .github/workflows/ ci/
Remediation
- Integrate dependency scanning into the build and deployment pipeline:
# GitHub Actions example - name: Audit dependencies run: npm audit --audit-level=high continue-on-error: false
- Define remediation SLAs:
Severity Remediation SLA Critical 24 hours High 7 days Medium 30 days Low 90 days - Pin dependency versions and use lock files (
package-lock.json,requirements.txtwith hashes). - Subscribe to security advisories for the MCP SDK and major dependencies.
- Run scans on a scheduled basis (minimum weekly) in addition to build-time checks.
Impact
Dependency updates may introduce breaking changes. Use automated testing to validate updates before deployment. Pin versions to avoid unintended updates.
Default Value
Not configured. MCP server deployments are not routinely scanned for dependency vulnerabilities.
References
- OWASP MCP Security Cheat Sheet, Section 5: Tool Supply Chain
- OWASP MCP Top 10: MCP03 (Tool Poisoning), MCP04 (Supply Chain Attacks & Dependency Tampering)
- EU AI Act, Article 15: Accuracy, Robustness and Cybersecurity
- NIST SP 800-53: SI-2 Flaw Remediation
- CWE-1395: Dependency on Vulnerable Third-Party Component
- CIS Controls v8.1: 16.4 (Establish and Maintain a Secure Coding Practices), 7.4 (Perform Automated Application Patch Management)
Description
Agents connecting to the MCP server SHOULD present a cryptographic identity assertion -- a signed token or certificate that binds the agent's identifier to a cryptographic key pair. This enables non-repudiable attribution of tool calls to specific agents and supports trust decisions based on verified identity rather than bearer tokens alone.
Rationale
Bearer tokens establish session authentication but can be shared, stolen, or delegated without the server's knowledge. The OWASP MCP Security Cheat Sheet covers the distinction between authentication (who is connecting) and identity (provable, non-repudiable attribution). Cryptographic identity is essential for regulated environments where auditors must attribute actions to specific agents. The IETF draft on agent identity defines a framework for cryptographic agent identity.
Audit
- Check the server configuration for agent identity requirements:
grep -A 10 "agent_identity" /etc/mcp-server/config.yaml - Attempt to connect with a bearer token but without an identity assertion:
curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -d '{"tool": "get_status", "arguments": {}}' | jq .error # For L2: Expected 403 with "agent_identity_required" for sensitive tools
- Verify the server validates agent identity signatures:
# Inspect server logs for identity verification grep "agent_identity" /var/log/mcp-server/audit.log | tail -5 # Expected: entries showing agent_id, issuer, and verification_status
Remediation
- Configure the server to accept and verify agent identity assertions:
agent_identity: enabled: true required_for: "sensitive_tools" # or "all_tools" supported_formats: - "jwt" # JSON Web Token (RFC 7519) - "x509" # Client certificate - "signed_assertion" # Signed agent identity assertion (e.g., IETF MCPS draft) trusted_issuers: - issuer: "https://idp.example.com" jwks_uri: "https://idp.example.com/.well-known/jwks.json" - issuer: "agent-registry.example.com" public_key: "/etc/mcp-server/trusted-issuers/registry.pem" required_claims: - "agent_id" - "iss" - "exp" - "capabilities"
- Agents present identity via a dedicated header:
X-Agent-Identity: eyJhbGciOiJFUzI1NiIsInR5cCI6ImFnZW50K2p3dCJ9... - The server verifies the signature, checks expiration, and logs the verified identity with each tool call.
Impact
Requires agents to obtain cryptographic identity assertions from a trusted issuer. Adds infrastructure requirements (issuer service, key management). Verification adds ~10-50ms per request.
Default Value
Not configured. No MCP server implementations support cryptographic agent identity natively.
References
- OWASP MCP Security Cheat Sheet, Section 3: Agent Identity
- OWASP MCP Top 10: MCP01 (Token Mismanagement & Secret Exposure), MCP07 (Insufficient Authentication & Authorization), MCP09 (Shadow MCP Servers)
- IETF Internet-Draft: draft-sharif-openid-agent-identity
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 6: Agent Identity)
- SPIFFE/SPIRE: spiffe.io (workload identity framework)
- CIS Controls v8.1 Gap: No existing control addresses cryptographic identity for autonomous AI agents. CIS Controls 5.x and 6.x cover human and workload identity management, but agent identity -- where an autonomous, non-human entity carries signed credentials and acts independently -- is entirely uncovered. This is an MCP-specific risk requiring new control guidance.
Description
When an agent presents a signed agent identity assertion (a structured, signed identity document containing the agent's identifier, capabilities, issuer, and behavioral attestations), the MCP server MUST verify the assertion's cryptographic signature, check its expiration, validate the issuer against a trusted issuer list, and confirm the agent's claimed capabilities are sufficient for the requested tool. Implementations may use JWT, JWS, X.509 certificates, or equivalent cryptographic identity credentials as defined by the IETF MCPS draft or similar specifications.
Rationale
An unverified identity assertion provides no more assurance than an unsigned claim. The OWASP MCP Security Cheat Sheet covers the full verification lifecycle for agent identity documents. Partial verification (e.g., checking the signature but not the issuer, or the issuer but not the expiration) leaves gaps that attackers can exploit with forged or expired credentials.
Audit
- Verify the server performs full assertion validation by testing with an expired credential:
# Use an identity assertion with exp claim in the past curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -H "X-Agent-Identity: <expired-assertion>" \ -d '{"tool": "read_file", "arguments": {"path": "/tmp/test"}}' | jq .error # Expected: "agent_identity_expired"
- Test with an assertion signed by an untrusted issuer:
curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -H "X-Agent-Identity: <untrusted-issuer-assertion>" \ -d '{"tool": "read_file", "arguments": {"path": "/tmp/test"}}' | jq .error # Expected: "untrusted_issuer"
- Test with an assertion lacking required capabilities:
# Assertion with capabilities=["read"] attempting a write tool curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <token>" \ -H "X-Agent-Identity: <read-only-assertion>" \ -d '{"tool": "write_file", "arguments": {"path": "/tmp/test", "content": "x"}}' | jq .error # Expected: "insufficient_capabilities"
Remediation
- Implement a complete identity assertion verification pipeline:
agent_identity_verification: steps: - verify_signature: true - check_expiration: true - validate_issuer: trusted_issuers_file: "/etc/mcp-server/trusted-issuers.json" allow_unknown_issuers: false - check_revocation: method: "crl" # or "ocsp" crl_url: "https://idp.example.com/crl" - match_capabilities: enforce: true on_failure: action: "deny" log_level: "warn"
- Verification sequence:
- Parse the identity assertion (JWT/JWS or equivalent format)
- Verify the signature using the issuer's public key
- Check
expclaim against current time (with configurable clock skew tolerance) - Validate
issclaim against trusted issuer list - Check revocation status (CRL or OCSP)
- Match
capabilitiesclaim against the tool's required capabilities
- Cache issuer public keys with a reasonable TTL (e.g., 1 hour) to reduce verification latency.
Impact
Full verification adds latency (signature verification + optional revocation check). CRL/OCSP checks add network dependency; consider caching or stapling. Requires maintaining a trusted issuer list.
Default Value
Not configured. Signed agent identity assertions are not a standard feature in current MCP implementations.
References
- OWASP MCP Security Cheat Sheet, Section 3: Agent Identity Verification
- OWASP MCP Top 10: MCP01 (Token Mismanagement & Secret Exposure), MCP07 (Insufficient Authentication & Authorization), MCP09 (Shadow MCP Servers)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 6: Agent Identity Verification)
- RFC 7519: JSON Web Token (JWT)
- CIS Controls v8.1 Gap: No existing control addresses verification of signed identity assertions for autonomous agents. This is an MCP-specific risk requiring new control guidance.
Description
The MCP server MUST support revocation of agent identities, such that a compromised, misbehaving, or decommissioned agent can be immediately blocked from accessing any tools. Revocation must take effect within a defined SLA (e.g., within 5 minutes) without requiring a server restart.
Rationale
Even with strong authentication and identity verification, agents can be compromised, their keys can be stolen, or they may exhibit unexpected behavior that necessitates immediate access revocation. The OWASP MCP Security Cheat Sheet covers identity lifecycle management including revocation. Without revocation support, the only recourse is to rotate server-side secrets (affecting all agents) or restart the server. EU AI Act Article 14 requires the ability to interrupt or override AI system operation.
Audit
- Check the server supports revocation:
grep -A 10 "revocation" /etc/mcp-server/config.yaml - Revoke an agent identity and verify it takes effect:
# Add agent to revocation list curl -X POST https://<mcp-server>/admin/revoke-agent \ -H "Authorization: Bearer <admin-token>" \ -d '{"agent_id": "agent-abc123", "reason": "compromised"}' # Attempt tool call with revoked agent curl -X POST https://<mcp-server>/mcp/v1/tools/call \ -H "Authorization: Bearer <revoked-agent-token>" \ -d '{"tool": "get_status", "arguments": {}}' | jq .error # Expected: "agent_revoked"
- Verify revocation took effect within the defined SLA:
grep "agent_revoked" /var/log/mcp-server/audit.log | tail -1 # Compare timestamp with revocation request timestamp
Remediation
- Implement agent revocation:
revocation: enabled: true methods: - type: "local_list" file: "/etc/mcp-server/revoked-agents.json" check_interval_seconds: 30 - type: "crl" url: "https://idp.example.com/agent-crl" cache_ttl_seconds: 300 - type: "api" endpoint: "/admin/revoke-agent" sla_seconds: 300 # 5-minute maximum propagation time
- Support multiple revocation triggers:
- Manual revocation via admin API
- Automated revocation based on behavioral anomalies
- External revocation via CRL or OCSP
- Log all revocation events with the reason and requesting administrator.
- Support "soft" revocation (block new tool calls but allow in-flight operations to complete) and "hard" revocation (immediately terminate all sessions).
Impact
Revocation checks add a lookup per request (sub-millisecond for local lists, variable for CRL/OCSP). The revocation list grows over time; implement periodic cleanup of expired revocations.
Default Value
Not configured. No MCP server implementations support agent identity revocation.
References
- OWASP MCP Security Cheat Sheet, Section 3: Agent Identity Lifecycle
- OWASP MCP Top 10: MCP01 (Token Mismanagement & Secret Exposure), MCP07 (Insufficient Authentication & Authorization), MCP09 (Shadow MCP Servers)
- IETF Internet-Draft: draft-sharif-mcps-secure-mcp (Section 6.3: Revocation)
- EU AI Act, Article 14: Human Oversight
- RFC 5280: Internet X.509 PKI Certificate and CRL Profile
- CIS Controls v8.1 Gap: No existing control addresses revocation of autonomous agent identities. Nearest: 5.3 (Disable Dormant Accounts), but agents are not user accounts -- they are autonomous entities with cryptographic credentials that require purpose-built revocation mechanisms (CRL, OCSP, or real-time revocation lists). This is an MCP-specific risk requiring new control guidance.
| Control | Profile | Automated | Description |
|---|---|---|---|
| 1.1 | L1 | Yes | MCP server requires authentication |
| 1.2 | L1 | Yes | Per-tool access control is configured |
| 1.3 | L2 | Partial | Graduated access control is implemented |
| 1.4 | L2 | Partial | Agent identity verification for sensitive tools |
| 2.1 | L1 | Yes | Per-message signing is enabled |
| 2.2 | L1 | Yes | Replay protection is configured |
| 2.3 | L2 | Yes | Tool definition signing is enabled |
| 2.4 | L2 | Yes | Canonical serialization (RFC 8785) for signing |
| 3.1 | L1 | Yes | Tool calls logged with timestamp and agent ID |
| 3.2 | L2 | Yes | Audit logs are tamper-evident |
| 3.3 | L1 | Partial | Audit log retention meets regulatory requirements |
| 3.4 | L2 | Yes | Audit logs support SIEM export |
| 4.1 | L1 | Yes | TLS 1.2+ required for HTTP transport |
| 4.2 | L1 | Yes | Rate limiting is configured |
| 4.3 | L1 | Yes | Error responses do not leak implementation details |
| 5.1 | L1 | Partial | Tool definitions are inventoried |
| 5.2 | L1 | Partial | Dangerous capabilities documented and justified |
| 5.3 | L2 | Yes | Tool definition changes trigger alerts |
| 5.4 | L1 | Yes | Dependencies audited for known vulnerabilities |
| 6.1 | L2 | Partial | Agents present cryptographic identity |
| 6.2 | L2 | Yes | Signed agent identity assertions verified before tool access |
| 6.3 | L2 | Yes | Agent identity revocation is supported |
Total Controls: 22 (L1: 12, L2: 10)
| Framework | Relevant Articles/Requirements | Controls |
|---|---|---|
| EU AI Act | Article 9 (Risk Management) | 1.2, 5.1, 5.2 |
| EU AI Act | Article 12 (Record-Keeping) | 1.4, 3.1, 3.2, 3.3 |
| EU AI Act | Article 14 (Human Oversight) | 1.3, 6.3 |
| EU AI Act | Article 15 (Cybersecurity) | 1.1, 4.1, 4.3, 5.4 |
| PCI DSS v4.0.1 | Req 4.2 (Cryptography) | 4.1 |
| PCI DSS v4.0.1 | Req 10.7 (Audit Retention) | 3.3 |
| OWASP MCP Top 10 | MCP01: Token Mismanagement & Secret Exposure | 1.1, 1.2, 1.3, 1.4, 6.1, 6.2, 6.3 |
| OWASP MCP Top 10 | MCP02: Privilege Escalation via Scope Creep | 1.1, 1.2, 1.3, 1.4 |
| OWASP MCP Top 10 | MCP03: Tool Poisoning | 2.1, 2.2, 2.3, 2.4, 5.1, 5.2, 5.3, 5.4 |
| OWASP MCP Top 10 | MCP04: Supply Chain Attacks & Dependency Tampering | 5.1, 5.2, 5.3, 5.4 |
| OWASP MCP Top 10 | MCP05: Command Injection & Execution | 4.1, 4.2, 4.3 |
| OWASP MCP Top 10 | MCP06: Intent Flow Subversion | 2.1, 2.2, 2.3, 2.4 |
| OWASP MCP Top 10 | MCP07: Insufficient Authentication & Authorization | 1.1, 1.2, 1.3, 1.4, 6.1, 6.2, 6.3 |
| OWASP MCP Top 10 | MCP08: Lack of Audit and Telemetry | 3.1, 3.2, 3.3, 3.4 |
| OWASP MCP Top 10 | MCP09: Shadow MCP Servers | 4.1, 4.2, 4.3, 6.1, 6.2, 6.3 |
| OWASP MCP Top 10 | MCP10: Context Injection & Over-Sharing | 4.3, 5.2 |
| NIST SP 800-53 | AC-3 (Access Enforcement) | 1.2, 1.3 |
| NIST SP 800-53 | SI-7 (Integrity) | 2.1, 5.3 |
| NIST SP 800-53 | AU-3 (Audit Content) | 3.1, 3.4 |
- OWASP MCP Security Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/MCP_Security_Cheat_Sheet.html
- OWASP MCP Top 10 -- https://owasp.org/www-project-mcp-top-10/
- IETF Internet-Draft: Secure MCP (MCPS) -- https://datatracker.ietf.org/doc/draft-sharif-mcps-secure-mcp/
- IETF Internet-Draft: Agent Payment Trust -- https://datatracker.ietf.org/doc/draft-sharif-agent-payment-trust/
- IETF Internet-Draft: OpenID Agent Identity -- https://datatracker.ietf.org/doc/draft-sharif-openid-agent-identity/
- EU AI Act -- https://eur-lex.europa.eu/eli/reg/2024/1689/oj
- PCI DSS v4.0.1 -- https://www.pcisecuritystandards.org/document_library/
- NIST SP 800-53 Rev. 5 -- https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final
- RFC 8785: JSON Canonicalization Scheme -- https://www.rfc-editor.org/rfc/rfc8785
- RFC 9421: HTTP Message Signatures -- https://www.rfc-editor.org/rfc/rfc9421
- Model Context Protocol Specification -- https://spec.modelcontextprotocol.io/
- CIS Benchmarks -- https://www.cisecurity.org/cis-benchmarks
- SPIFFE/SPIRE -- https://spiffe.io/
This appendix maps each benchmark control to the closest CIS Controls v8.1 control, identifying gaps where MCP-specific risks are not addressed by the existing CIS framework.
Summary: 22 controls total. 10 map directly to existing CIS Controls. 9 are MCP-specific gaps with no CIS equivalent. 3 are partial mappings where CIS covers the general category but not the MCP-specific requirement.
| Control | Description | CIS Controls v8.1 Mapping | Gap? |
|---|---|---|---|
| 1.1 | Authentication required | 6.3 (MFA for Externally-Exposed Applications), 6.7 (Centralize Access Control) | No |
| 1.2 | Per-tool access control | 6.8 (RBAC), 3.3 (Data Access Control Lists) | No |
| 1.3 | Graduated access control | -- | Yes: graduated agent trust based on verification strength |
| 1.4 | Agent identity for sensitive tools | -- | Yes: autonomous agent identity verification |
| 2.1 | Per-message signing | -- | Yes: application-layer message signing and non-repudiation |
| 2.2 | Replay protection | -- | Yes: application-layer replay attack prevention |
| 2.3 | Tool definition signing | -- | Yes: dynamic tool definition integrity |
| 2.4 | Canonical serialization | -- | Yes: deterministic serialization for signing |
| 3.1 | Tool call logging | 8.2 (Collect Audit Logs), 8.5 (Collect Detailed Audit Logs) | No |
| 3.2 | Tamper-evident logs | 8.9 (Centralize Audit Logs) | Partial: CIS covers centralization but not cryptographic tamper-evidence |
| 3.3 | Log retention | 8.10 (Retain Audit Logs) | No |
| 3.4 | SIEM export | 8.9 (Centralize Audit Logs), 8.11 (Conduct Audit Log Reviews) | No |
| 4.1 | TLS 1.2+ | 3.10 (Encrypt Sensitive Data in Transit) | No |
| 4.2 | Rate limiting | 13.3 (Network Intrusion Prevention Solution) | Partial: MCP requires per-agent, per-tool application-layer rate limiting |
| 4.3 | Error handling | 16.1 (Secure Application Development Process) | Partial: CIS covers secure development but not MCP-specific error context leakage |
| 5.1 | Tool inventory | 2.1 (Establish and Maintain a Software Inventory) | No |
| 5.2 | Dangerous tool documentation | 2.5 (Allowlist Authorized Software) | No |
| 5.3 | Tool change alerts | -- | Yes: runtime tool definition change detection |
| 5.4 | Dependency audit | 16.4 (Secure Coding Practices), 7.4 (Automated Application Patch Management) | No |
| 6.1 | Cryptographic agent identity | -- | Yes: autonomous agent cryptographic identity |
| 6.2 | Identity assertion verification | -- | Yes: signed agent identity assertion verification |
| 6.3 | Agent identity revocation | -- | Yes: agent identity revocation mechanisms |
The 9 MCP-specific gaps cluster into three categories:
-
Agent Identity (3 gaps: 1.3, 1.4, 6.1, 6.2, 6.3) -- CIS Controls address human and workload identity but have no framework for autonomous AI agents that carry signed credentials, act independently, and require purpose-built revocation. This is the largest gap area.
-
Message-Layer Security (4 gaps: 2.1, 2.2, 2.3, 2.4) -- CIS Controls cover transport encryption (TLS) but not application-layer message signing, replay protection, or tool definition integrity. MCP's architecture -- where messages pass through intermediaries and tool definitions are served dynamically -- requires protocol-level security controls that do not exist in the current CIS framework.
-
Dynamic Tool Supply Chain (1 gap: 5.3) -- CIS Controls cover software inventory and allowlisting for installed software, but MCP tool definitions are dynamically served at runtime and can be poisoned without modifying any installed component. File integrity monitoring (FIM) does not detect changes to in-memory or API-served tool schemas.
These gaps represent the primary contribution of this benchmark to the CIS ecosystem: identifying where the existing 18 CIS Control families fall short for MCP deployments and providing concrete, auditable controls to fill those gaps.
This document is a community draft prepared for the CIS MCP Security Benchmark working group. It is not a final CIS publication and should not be distributed as an official CIS benchmark.
Prepared by Raza Sharif, CyberSecAI Ltd. Version 1.0.0-draft, 29 March 2026