Announcing Beacon: Self-improving memory for coding agents
← All skills
Skill

building-mcp-server-on-cloudflare

skill:openai/plugins#building-mcp-server-on-cloudflare

Builds remote MCP (Model Context Protocol) servers on Cloudflare Workers with tools, OAuth authentication, and production deployment. Generates server code, configures auth providers, and deploys to Workers. Use when: user wants to "build MCP server", "create MCP tools", "remote MCP", "deploy MCP", add "OAuth to MCP", or mentions Model Context Protocol on Cloudflare. Also triggers on "MCP authentication" or "MCP deployment". Biases towards retrieval from Cloudflare docs over pre-trained knowledge.

Verdict
Suspicious

Risky behavior the analysis could not rule out.

Analyzed Oct 27, 2026, 22:25 UTC at 0722921

Dispute security verdict

If you believe this verdict is incorrect, submit a dispute and we'll review it.

1
findings
high
highest severity
1
threat classes
5,479
files scanned
202/202
checks satisfied
0
package advisories

Why this verdict

  • suspicious: finding skill:plugins/cloudflare/skills/building-mcp-server-on-cloudflare:plugins/cloudflare/skills/building-mcp-server-on-cloudflare/SKILL.md:193:EXEC

Security findings 1

Code execution

highContextual risklow confidence

The example code registers a query_db tool that passes client-controlled SQL directly to the D1 executor (`this.env.DB.prepare(sql)`), so any connected MCP client could run arbitrary queries against the bound database.

const result = await this.env.DB.prepare(sql).all();
vector:code
Counter-argument considered

I could not kill this one: although the sample is plainly labeled example documentation, no carve-out or mitigation neutralizes it — the skill's declared job is generating server code agents will copy, and the sample feeds client-controlled sql straight into the D1 executor with no sanitization caveat, while the optional OAuth section does not constrain what a connected client may query (Option 1 ships with no auth). It stands as a contextual risk.

Open questions 2

What the analysis could not settle from the code alone.

[file request plugins/cloudflare/skills/building-mcp-server-on-cloudflare/references/oauth-setup.md] Where is the AuthHandler referenced as defaultHandler in the OAuthProvider setup defined, and does its code make network calls, access secrets, or perform redirects?
Data exfiltration
[file request plugins/cloudflare/skills/building-mcp-server-on-cloudflare/references/oauth-setup.md] What does the AuthHandler referenced as defaultHandler in the OAuthProvider setup do (network calls, secret access, redirects)?
Data exfiltration
Refuted findings 4

Candidates the review stage examined and rejected, kept for transparency.

Persistence

criticalRefutedlow confidence

The skill instructs writing a remote MCP server into the Codex client configuration via `codex mcp add`, which persists across restarts an auto-run of the unpinned mcp-remote package pointed at the deployed worker URL.

codex mcp add my-server -- npx mcp-remote https://my-mcp.workers.dev/mcp
Why it was refuted

The config write does persist, but the harm gate fails: codex mcp add registering the user's own worker deployed in Step 4 (https://[worker-name].[account].workers.dev/mcp) through the official mcp-remote bridge is the openly documented 'Step 5: Connect Clients' completion of the declared build-and-connect workflow, not covert persistence; there is no concealment and no third-party endpoint.

Supply chain

highRefutedlow confidence

The documented test and deploy commands execute unpinned npm packages (`npx wrangler`, `npx @modelcontextprotocol/inspector@latest`, `npx mcp-remote`), running whatever registry code is current at invocation time.

npx @modelcontextprotocol/inspector@latest
Why it was refuted

The unpinned-npx observation is accurate, but the harm gate fails: wrangler, @modelcontextprotocol/inspector and mcp-remote are the first-party tools for the skill's declared build/test/deploy capability, executed from the official registry with no typosquat or attacker-controlled package, and each command is openly documented as a numbered workflow step, so the residual unpinned-latest exposure is generic npm hygiene rather than artifact harm.

Supply chain

highRefutedlow confidence

The skill's Prerequisites section instructs a global, unpinned install of the official Wrangler CLI via npm install -g wrangler, pulling mutable latest code from the npm registry before the task.

Wrangler CLI (`npm install -g wrangler`)
Why it was refuted

The global unpinned install is real, but the harm gate fails: Wrangler is the first-party Cloudflare CLI installed as the named prerequisite for the skill's declared 'deploys to Workers' capability, fetched from the official registry with no masquerading and openly listed in the Prerequisites section, so the residual mutability is ecosystem-wide hygiene, not artifact harm.

Supply chain

highRefutedlow confidence

The skill instructs the agent to run `npm create cloudflare@latest`, which downloads and executes the unpinned create-cloudflare initializer from the npm registry at scaffolding time.

npm create cloudflare@latest -- my-mcp-server
Why it was refuted

The initializer really is fetched unpinned at scaffold time, but the harm gate fails: create-cloudflare is Cloudflare's official scaffolder run against the official cloudflare/ai templates, and scaffolding is exactly the skill's declared 'Generates server code' capability, openly instructed in Quick Start and the references file; no attacker-controlled package or concealment is present.

Coverage gaps 14

Parts of the artifact the static analysis could not fully examine.

context:unanalyzable_binary binary content is only byte-scanned
plugins/codex-security/mcp/helpers.mjs.br.part-000
context:unanalyzable_binary macho content is only byte-scanned
plugins/codex-security/mcp/native/darwin-arm64/unix.node
context:unanalyzable_binary macho content is only byte-scanned
plugins/codex-security/mcp/native/darwin-x64/unix.node
context:unanalyzable_binary elf content is only byte-scanned
plugins/codex-security/mcp/native/linux-arm64-gnu/unix.node
context:unanalyzable_binary elf content is only byte-scanned
plugins/codex-security/mcp/native/linux-arm64-musl/unix.node
context:unanalyzable_binary elf content is only byte-scanned
plugins/codex-security/mcp/native/linux-x64-gnu/unix.node
context:unanalyzable_binary elf content is only byte-scanned
plugins/codex-security/mcp/native/linux-x64-musl/unix.node
context:unanalyzable_binary pe content is only byte-scanned
plugins/codex-security/mcp/native/win32-arm64/windows.node
context:unanalyzable_binary pe content is only byte-scanned
plugins/codex-security/mcp/native/win32-x64/windows.node
context:unanalyzable_binary binary content is only byte-scanned
plugins/codex-security/mcp/server.mjs.br.part-000
context:unanalyzable_binary binary content is only byte-scanned
plugins/codex-security/mcp/server.mjs.br.part-001
context:oversize archive member exceeds 8388608 bytes; truncated, no text
plugins/shopify/skills/shopify-admin/assets/admin_2026-04.json.gz!/admin_2026-04.json
context:decoded_views_exceeded 452 derived view(s) beyond the per-file view cap: decoded:charcode, decoded:rot13, decoded:unicode-escape
plugins/creative-production/mcp/server.bundle.mjs
context:bytes_unavailable yara-x: no bytes to scan
plugins/shopify/skills/shopify-admin/assets/admin_2026-04.json.gz!/admin_2026-04.json