Add SHA-256 integrity verification to MCP server allowlist in requirements.toml

Resolved 💬 3 comments Opened Mar 26, 2026 by RubenSantaclara Closed May 10, 2026

What variant of Codex are you using?

CLI, App, and IDE Extension (all surfaces that enforce requirements.toml)

What feature would you like to see?

<html>
<body>
<!--StartFragment--><html><head></head><body>
<h2>Summary</h2>
<p>Proposal to extend the <code>identity</code> field of the MCP server allowlist in <code>requirements.toml</code> with an optional <code>sha256</code> field that verifies artifact integrity before execution. This complements the existing managed config enterprise mechanism in Codex, closing the gap between "the admin approves a server by name" and "the artifact that runs is actually the one the admin approved."</p>
<hr>
<h2>Problem</h2>
<p>Codex Enterprise already provides an MCP server allowlist in <code>requirements.toml</code>, where administrators can restrict which servers are permitted via the <code>identity</code> field:</p>
<pre><code class="language-toml">[mcp_servers.docs]
identity = { command = "codex-mcp" }

[mcp_servers.remote]
identity = { url = "https://example.com/mcp" }
</code></pre>
<p>When this allowlist is configured, Codex enables an MCP server only when both its name and identity match an approved entry. However, identity verification is currently limited to string comparison: the command name or URL. <strong>There is no cryptographic verification of the artifact that actually executes.</strong></p>
<p>This means a binary that matches on name and command path will pass validation even if it has been tampered with after installation. The allowlist protects against unauthorized servers, but not against modification of authorized ones.</p>
<h3>Attack vectors the current allowlist does not cover</h3>
<p><strong>Supply chain — Post-installation tampering:</strong>
An attacker (or a malicious process on the developer's machine) modifies the MCP server binary after installation. The command name still matches the allowlist, so Codex executes it without detecting the tampering. The compromised server can exfiltrate tokens, source code, or repository data while appearing to function normally.</p>
<p><strong>Typosquatting with command name match:</strong>
If the allowlist validates only the executable name (e.g. <code>github-mcp-server</code>), a malicious package that installs a binary with the same name in a higher-precedence <code>PATH</code> directory would pass verification.</p>
<p><strong>Unauthorized update:</strong>
A developer updates an MCP server to a version not evaluated by the security team. The allowlist continues to validate because the command name didn't change, but the artifact's behavior did.</p>
<h3>Industry evidence</h3>
<p>This gap is widely documented:</p>
<ul>
<li>
<p><strong>Palo Alto Networks</strong> (May 2025): MCP server packages currently lack digital signatures, preventing users from easily verifying their authenticity or integrity. Without digital signatures, attackers could silently modify these packages — injecting malicious code or altering their functionality.</p>
</li>
<li>
<p><strong>Microsoft Security</strong> (May 2025): MCP's lack of unique tool identifiers allows attackers to create malicious tools with names identical or similar to legitimate ones. Recommends using cryptographic signatures and maintaining authenticated repositories of trusted servers.</p>
</li>
<li>
<p><strong>Red Hat</strong> (November 2025): If an MCP server is offered as a cloud service, it should implement cryptographic server verification so clients can verify the server. Developers and users must verify the integrity of all dependencies they use.</p>
</li>
<li>
<p><strong>Hou et al.</strong> (2025): Demonstrates typosquatting attacks where clients select servers solely based on names and descriptions, showing no preference or verification mechanism. Recommends cryptographically verifiable server identities through signed manifests that bind namespaces to verified publishers.</p>
</li>
<li>
<p><strong>Yan et al. — MICRYSCOPE</strong> (December 2025): First framework for detecting cryptographic misuse in MCP implementations. Confirms the protocol lacks built-in support for request–response authenticity and confidentiality.</p>
</li>
</ul>
<hr>
<h2>Proposed solution</h2>
<h3>Extend the <code>identity</code> field with <code>sha256</code></h3>
<p>The proposal is minimally invasive: add an optional <code>sha256</code> field to the existing <code>identity</code> object in <code>requirements.toml</code>. When present, Codex computes the SHA-256 hash of the server binary before starting the process and compares it against the declared value. If it doesn't match, the server is rejected.</p>
<pre><code class="language-toml"># requirements.toml — Existing managed configuration

Proposed extension: sha256 field in identity

[mcp_servers.github]
identity = {
command = "github-mcp-server",
sha256 = "a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890"
}

[mcp_servers.sentry]
identity = {
command = "/opt/mcp-servers/sentry-mcp-server",
sha256 = "b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890ab"
}
</code></pre>
<h3>Behavior</h3>

Scenario | sha256 present | Result
-- | -- | --
Server in allowlist, hash matches | Yes | Server enabled
Server in allowlist, hash mismatch | Yes | Server blocked + audit log
Server in allowlist, no sha256 field | No | Current behavior (name/command match only)
Server not in allowlist | — | Server disabled (current behavior)
Empty mcp_servers in requirements | — | All servers disabled (current behavior)
No mcp_servers section in requirements.toml | — | No restrictions (current behavior)

<p>The <code>sha256</code> field is optional to maintain full backward compatibility. Administrators who only need a name-based allowlist can continue using the current syntax unchanged.</p>
<h3>Verification flow</h3>
<pre><code>Codex starts MCP server


Is it in the requirements.toml allowlist?

NO ──┤──► Disable server (current behavior)

YES ─▼
Does the identity field have sha256?

NO ──┤──► Validate name/command only (current behavior)

YES ─▼
Resolve absolute path of the binary (which / where)


Compute SHA-256 of the file


Computed hash == declared sha256?

NO ──┤──► Block + emit error + audit log

YES ─▼
Start MCP server process
</code></pre>
<h3>Hash resolution for different installation types</h3>
<p><strong>Direct binary (absolute path):</strong>
The simplest case. The administrator specifies the absolute path in <code>command</code> and Codex computes the hash directly on that file.</p>
<pre><code class="language-toml">identity = {
command = "/opt/mcp-servers/sentry-mcp",
sha256 = "b2c3d4..."
}
</code></pre>
<p><strong>Binary in PATH (command name):</strong>
Codex resolves the absolute path using <code>which</code> (Unix) or <code>where</code> (Windows) and computes the hash on the resolved file.</p>
<pre><code class="language-toml">identity = {
command = "github-mcp-server",
sha256 = "a1b2c3..."
}
</code></pre>
<p><strong>Servers via <code>npx -y</code> (dynamic download):</strong>
This case is incompatible with static hash verification because <code>npx</code> downloads the package dynamically. For these servers, administrators should require pre-installation and use the installed binary path. This is a documented constraint, not a bug.</p>
<h3>Error messages</h3>
<p>Messages should be clear and actionable, consistent with the existing Codex style when rejecting configuration that violates <code>requirements.toml</code>:</p>
<pre><code>MCP server blocked: integrity check failed

Server: github-mcp
Binary: /usr/local/bin/github-mcp-server
Expected: sha256:a1b2c3d4e5f6...
Actual: sha256:ff00112233aa...

The server binary does not match the hash approved by your
administrator in requirements.toml. This could indicate
tampering or an unapproved update.

Contact your Codex administrator to update the approved hash.
</code></pre>
<h3>Audit logging</h3>
<p>Codex already emits structured events via OpenTelemetry (OTel configuration in <code>managed_config.toml</code>). Integrity verification events should follow the same pattern:</p>
<pre><code class="language-json">{
"name": "codex.mcp_integrity_check",
"timestamp": "2026-03-25T10:30:00Z",
"attributes": {
"mcp.server_name": "github-mcp",
"mcp.server_type": "stdio",
"mcp.command": "/usr/local/bin/github-mcp-server",
"mcp.integrity.result": "blocked",
"mcp.integrity.reason": "hash_mismatch",
"mcp.integrity.expected_sha256": "a1b2c3d4...",
"mcp.integrity.actual_sha256": "ff001122...",
"codex.version": "0.x.y"
}
}
</code></pre>
<p>This allows security teams to monitor tampered server execution attempts through their existing OTel/SIEM pipeline with no additional configuration.</p>
<hr>
<h2>Proposed scope</h2>
<ol>
<li><strong>Extend the <code>identity</code> schema in <code>requirements.toml</code></strong>: Add optional <code>sha256</code> field (string, hex-encoded, 64 characters).</li>
<li><strong>Hash verification for stdio servers</strong>: Before spawning the process, resolve the binary path, compute SHA-256, and compare against the declared value.</li>
<li><strong>Clear error messages</strong>: On verification failure, show expected vs. actual hash and recommended action.</li>
<li><strong>OTel event <code>codex.mcp_integrity_check</code></strong>: Emitted on every verification (success and failure).</li>
<li><strong>Unit tests</strong>: Hash match, hash mismatch, missing <code>sha256</code> field (fallback to current behavior), binary not found.</li>
<li><strong>Documentation</strong>: Update the <code>mcp_servers</code> section in <code>requirements.toml</code> documentation.</li>
</ol>
<hr>
<h2>Affected modules</h2>
<p>Based on the <code>openai/codex</code> repository structure:</p>
<ul>
<li><strong><code>codex-rs/core/</code></strong> — Configuration structs. Extend <code>McpServerIdentity</code> (or equivalent) with the optional <code>sha256</code> field.</li>
<li><strong><code>codex-rs/mcp-client/</code></strong> (or wherever MCP servers are resolved and spawned) — Enforcement point: compute binary hash before <code>spawn</code> and compare against declared value.</li>
<li><strong>Requirements logic</strong> — Where the <code>mcp_servers</code> allowlist is applied. Integrate hash verification into the existing name + identity matching flow.</li>
<li><strong>OTel event emission</strong> — Add the <code>codex.mcp_integrity_check</code> event to the existing telemetry pipeline.</li>
</ul>
<hr>
<h2>Compatibility</h2>
<ul>
<li><strong>Fully backward compatible</strong>: The <code>sha256</code> field is optional. Existing <code>requirements.toml</code> files continue to work unchanged.</li>
<li><strong>Gradual opt-in</strong>: Administrators can add hashes to critical servers first and expand progressively.</li>
<li><strong>No significant performance impact</strong>: Computing SHA-256 of a typical MCP server binary (a few MB) takes milliseconds.</li>
</ul>
</body>
</html>

Additional information

References

  1. Palo Alto Networks. "MCP Security Exposed: What You Need to Know Now". May 2025.

https://live.paloaltonetworks.com/t5/community-blogs/mcp-security-exposed-what-you-need-to-know-now/ba-p/1227143

  1. Microsoft. "Plug, Play, and Prey: The security risks of the Model Context Protocol". May 2025.

https://techcommunity.microsoft.com/blog/microsoftdefendercloudblog/plug-play-and-prey-the-security-risks-of-the-model-context-protocol/4410829

  1. Red Hat. "Model Context Protocol (MCP): Understanding security risks and controls". November 2025.

https://www.redhat.com/en/blog/model-context-protocol-mcp-understanding-security-risks-and-controls

  1. Hou, X. et al. "Model Context Protocol (MCP): Landscape, Security Threats, and Future Research Directions". 2025.

https://xinyi-hou.github.io/files/hou2025mcp_1.pdf

  1. Yan, B. et al. "MCP Does Not Stand for Misuse Cryptography Protocol". December 2025.

https://www.arxiv.org/pdf/2512.03775

  1. Aembit. "MCP Security Vulnerabilities: Complete Guide for 2026". March 2026.

https://aembit.io/blog/the-ultimate-guide-to-mcp-security-vulnerabilities/

  1. Codex official documentation — Managed configuration.

https://developers.openai.com/codex/enterprise/managed-configuration

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗