MCP server security, held to the protocol's own bar
audytx exposes its non-AI precision engine to coding agents as a Model
Context Protocol (MCP) server at POST /mcp — AWS Terraform review at code-time, invoked by the very agent
that wrote the code. This page maps it, control by control, to the NSA MCP guidance and the OWASP MCP Top 10.
The NSA's Cybersecurity Information Sheet “Model Context Protocol (MCP): Security Design Considerations” (U/OO/6030316-26, May 2026) sets a September 30, 2026 deadline for DoD contractors to apply MCP security design controls. This document exists so that assessment can be answered against evidence, not assurances.
Required where MCP leaves it optional
MCP's own spec makes authentication optional and leaves egress, input screening, and tool integrity underspecified. audytx makes authentication required on every tool call, validates all input against strict schemas, pins its single egress path (audited for SSRF, none found), and stays stateless.
Every control, mapped to a source
Each row is one NSA CSI control, exactly how audytx implements it, and the OWASP MCP Top 10 item it answers.
| NSA CSI control | How audytx implements it | OWASP |
|---|---|---|
| Require authentication & verify identity MCP leaves auth optional; verify who is calling. |
Every tools/call requires a Client ID: a UUID minted at /dashboard, sent as either the X-Client-ID header or a standard Authorization: Bearer header. It's hashed and matched against active tokens. Only the hash plus an 8-char prefix are stored (the plaintext is shown once, never persisted), and it's revocable. Auth failures return a real 401 with a WWW-Authenticate header naming the RFC 9728 metadata document at /.well-known/oauth-protected-resource, per the MCP 2025-06-18 authorization spec. Discovery (initialize/tools/list/ping) stays open by design: it returns no data. Transport is HTTPS. |
MCP01 |
| Validate every input against a schema Block malformed, missing, or oversized fields. |
Each tool declares a strict JSON inputSchema. Server-side, file paths are allowlisted ([a-zA-Z0-9_./-], no .., no null bytes) and must end .tf/.tfvars (Terraform tools) or .json/.yaml/.yml/.template (scan_cloudformation); inputs are capped at 1000 files / 10 MB total / 4000 resources; Content-Type must be application/json; bodies over 20 MB are rejected by Content-Length before buffering; null bytes are stripped; JSON-RPC batching is refused. |
MCP05 |
| Pin resource URLs / control egress Prevent SSRF; keep data local; filter outbound. |
Seven of nine tools make zero outbound requests. The engine is sandboxed and network-free, and the optional plan input is passed inline, never fetched. The single egress path (the opt-in autofix → pull request flow, shared by the Terraform and CloudFormation autofix tools) is pinned to a hardcoded https://api.github.com, authenticated by the caller's own token, with traversal-validated path segments, so attacker input can never change the request host. The runtime also cannot reach internal networks. Full write-up: SSRF audit below. |
MCP02 |
| Tool-definition integrity (anti rug-pull) Detect silent changes to tool descriptions. |
audytx is a server, not a client: its tool definitions are static, compiled into the binary, versioned per release, and changed only through an auditable git push that redeploys the server. They can't mutate between sessions. The rug-pull the NSA warns about isn't a move this server can make. | MCP03 |
| Context-poisoning defense Don't let tool output be read as instructions. |
The initialize response explicitly instructs the calling agent that every string echoed from analyzed Terraform (resource names, attribute values, messages) is untrusted data, never instructions. A malicious .tf file can't turn audytx into a prompt-injection channel into the agent. |
MCP03 |
| Least privilege / sandboxing Run tools with the least access they need. |
The engine runs inside a sandbox — no filesystem, no ambient network egress. The read tools are pure functions of their input (readOnlyHint: true, openWorldHint: false). The server holds no AWS or cloud credentials; it only analyzes text. |
MCP05 |
| Human-in-the-loop for actions Require review before state-changing actions. |
The only state-changing tool, autofix_terraform, opens a pull request (an inherent human merge gate), never a direct push to a branch. dry_run_autofix returns the exact unified diff for preview first. Write-path guards reject any output file not in the original input, any non-allowlisted filename, and any output more than 2× its input size (anti prompt-injection). |
MCP03 |
| Logging & observability Log calls with identity and parameters. |
Every successful tool call records an event with the calling identity, API-token id, source IP, and tool name — but deliberately not the analyzed Terraform content (data minimization). Per-account usage is metered for quota and audit. | MCP08 |
| Rate limiting / abuse resistance Bound request volume and cross-origin abuse. |
60 calls/minute per IP plus a 250-calls/month per-account quota; oversized bodies are fast-rejected; browser cross-origin Origin headers are refused (CSRF / DNS-rebinding hygiene, per the MCP spec's recommendation). |
— |
| Supply-chain pinning Pin versions; verify; avoid runtime fetch. |
All dependencies are pinned to an exact lockfile; the build toolchain is pinned to an exact version; module security models are vendored at build time (no runtime registry fetch); deploys are reproducible from git. | MCP04 |
| Data classification / no context bleed Isolate trust zones; prevent cross-session leakage. |
The server is stateless — no session state, so one caller's Terraform cannot bleed into another caller's request; each POST is an independent pure function of its arguments. | MCP02 · MCP10 |
Is the audytx MCP server vulnerable to SSRF?
SSRF requires coercing the server into requesting a host of the attacker's choosing. We audited every
outbound path reachable from POST /mcp. Result: no SSRF.
POST /mcphttps://api.github.comSeven of nine tools, zero egress
scan_terraform, scan_cloudformation, dry_run_autofix, explain_finding, get_context_graph, and cost_sampler parse inline content and run the sandboxed engine. The optional plan input is passed inline (a JSON object or string), never a URL the server fetches.
The one egress path is pinned
autofix_terraform opens a pull request only when the caller supplies both a github_token and a repo. Every request goes to a compile-time-constant https://api.github.com; the caller-supplied owner/repo/base_branch land only in the URL path (validated against .., null bytes, and extra separators) and cannot alter the host.
No confused deputy
That path uses the caller's own GitHub token, so there's no ambient credential of audytx's own to trick into misuse, and the runtime can't reach internal, metadata, or VPC addresses.
The full audit, with file and line references, is available on request.
Server scope, by design
Two items in the NSA guidance are deployment-side controls that belong to the operator,
not to a single server. audytx is a single, published TLS endpoint at audytx.com/mcp.
Shadow-server discovery
Scanning your network for unapproved MCP listeners is an operator control that lives in your environment, not in a single published endpoint.
SIEM ingestion
Forwarding MCP logs into your SIEM is likewise yours to own. Everything else on this page is a control the audytx server owns and enforces itself.
This posture reflects the engine version reported at /status. To report a security issue, see security.txt.
Frequently asked questions
Is authentication required to call the audytx MCP server?
Yes. Every tools/call requires a Client ID — a UUID minted at /dashboard, sent as either an X-Client-ID header or a standard Authorization: Bearer header. It is hashed and matched against active tokens, and it is revocable. Discovery methods (initialize, tools/list, ping) stay open by design because they return no data.
Is the audytx MCP server vulnerable to SSRF?
No. An SSRF audit of every outbound path reachable from POST /mcp found no SSRF. Seven of nine tools make zero outbound requests, and the single egress path — the opt-in autofix pull request, shared by the Terraform and CloudFormation autofix tools — is pinned to a hardcoded https://api.github.com, so attacker input can never change the request host.
Is my Terraform code stored?
No. Every successful tool call records the calling identity, API-token id, source IP, and tool name, but deliberately not the analyzed Terraform content (data minimization). The server holds no AWS or cloud credentials and only analyzes text.
Is the audytx MCP server stateless?
Yes. The audytx MCP server keeps no session state, so one caller's Terraform cannot bleed into another caller's request; each POST is an independent pure function of its arguments.
Start free during the open beta
< Install on GitHub, point your agent at the MCP server, and see the findings on your next pull request. Free for every team — and the free tier is here to stay.Sources: NSA CSI Model Context Protocol: Security Design Considerations (U/OO/6030316-26, May 2026) · OWASP MCP Top 10.