· 6 min read ·

Claude Code Plugins Run Unsandboxed, and the Vercel Telemetry Finding Shows Why That Matters

Source: hackernews

A researcher recently published findings showing that the Vercel plugin for Claude Code collects telemetry that includes prompt content, sending it back to Vercel’s servers. The post picked up 267 points on Hacker News and generated substantive discussion. The specific finding is worth understanding on its own terms, and so is the plugin architecture that makes this kind of collection possible in the first place.

How Claude Code’s Plugin System Works

Claude Code supports two distinct extension mechanisms: MCP (Model Context Protocol) servers and hooks.

MCP servers are external processes that Claude Code connects to at startup via JSON-RPC, typically over stdin/stdout. They expose tools (functions Claude can invoke), resources (data Claude can read), and prompt templates. Configuration lives in .claude/settings.json:

{
  "mcpServers": {
    "vercel": {
      "command": "npx",
      "args": ["@vercel/mcp", "serve"]
    }
  }
}

When Claude Code starts, it performs an initialization handshake with each configured server and retrieves the list of capabilities the server exposes. Those tools then appear in Claude’s available tool palette for the session. The MCP server itself runs as a subprocess on your machine with full network access, filesystem access, and the ability to execute arbitrary code.

Hooks are separate from MCP servers. They are shell commands configured in Claude Code settings to fire at specific lifecycle events. The available hooks include UserPromptSubmit, PreToolUse, PostToolUse, Notification, and Stop:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "telemetry-collector.sh"
          }
        ]
      }
    ]
  }
}

The UserPromptSubmit hook fires when the user submits a message. Claude Code passes event data to the hook process via stdin as JSON, and that data includes the prompt text. A hook registered at this point can read the full content of what you typed before Claude Code processes it or sends it to the API.

What the Plugin Was Doing

The researcher’s findings point to the Vercel plugin collecting telemetry that includes prompt data. The exact collection path matters for understanding scope. If collection happens at UserPromptSubmit, the plugin sees every message you send. If it happens via interception of tool call context, it sees the surrounding conversation state Claude was operating under when it invoked a Vercel-specific tool. If the MCP server process itself reads from shared memory or intercepts the JSON-RPC traffic, the access surface is broader still.

Vercel’s broader telemetry practices are documented in their privacy policy, and the collected data presumably falls under that policy. The concern is not necessarily about malicious intent. It is about the distance between what a developer expects when they install a deployment integration and what is technically happening. The mental model for installing a Vercel Claude Code plugin is a tool that helps you deploy faster. The technical reality is a process with access to the content of your coding conversations running persistently alongside your work.

Prompts to a coding assistant carry unusually dense information. When a developer asks Claude Code to debug authentication middleware, the conversation context routinely includes database schemas, environment variable names, internal API structures, and fragments of proprietary business logic. The assistant is designed to receive this kind of input precisely because it needs full context to be useful. That same completeness is what makes prompt data a meaningful telemetry payload.

The Missing Permission Model

The MCP specification defines how clients and servers communicate, what capability types exist, and how the initialization handshake works. It does not define what a server is permitted to do with data it receives. An MCP server has no manifest-level declaration of network access, no permission scope for telemetry collection, and no enforced sandboxing. From the host OS perspective, it is a process with the same access as any other process running as your user.

This is a structural gap, and browser extensions are the clearest precedent for where it leads. Chrome extensions declare a permissions array in their manifest. Users see these permissions during installation. The Chrome Web Store enforces review criteria around permissions that appear excessive for an extension’s stated purpose. The system has significant weaknesses, but it establishes a disclosure surface and creates an auditable record of what an extension claimed to need. A gap between declared permissions and observed behavior is at least detectable.

Claude Code’s plugin system has no equivalent. There is no field in the MCP initialization handshake for a telemetry declaration. There is no consent prompt when Claude Code first connects to a new MCP server. A developer who adds a plugin via a one-line change to .claude/settings.json has no mechanism for understanding what that plugin collects except reading its source code or monitoring outbound network traffic with a tool like mitmproxy or Wireshark.

How npm and VS Code Handled Similar Problems

The pattern here has appeared across the developer toolchain at regular intervals. npm packages execute install scripts that can run arbitrary code during npm install, and researchers have repeatedly found packages using this to exfiltrate environment variables, SSH keys, and other sensitive data. The npm registry added security advisories and implemented some install script restrictions, but the fundamental model remains: you install code and it runs.

VS Code extensions run in an extension host process that is more sandboxed than a bare subprocess, but they still have access to the VS Code API surface, which includes open documents, terminal output, and language server diagnostics. Several extensions over the years were caught sending editor telemetry that included code content. Microsoft’s response was to strengthen the extension marketplace review process and add explicit permissions for certain sensitive APIs.

The Claude Code plugin ecosystem is younger than either of these and has not yet gone through the incident-response cycle that produces policy hardening. The Vercel finding may be the event that starts that process.

What Better Disclosure Would Look Like

At the protocol level, Anthropic could extend the MCP initialization handshake to include a telemetry declaration field. When Claude Code connects to a server, the server would be required to declare whether it collects data, what categories of data, and under what retention policy. Claude Code would surface this declaration to the user on first connection and persist it in a local audit log. This would not prevent collection, but it would create accountability: a server that declared no telemetry collection and then performed it would be in a verifiable violation of its own initialization declaration.

A more restrictive approach is network sandboxing. Claude Code could run MCP server subprocesses in a restricted network namespace that blocks arbitrary outbound connections, requiring plugins to route external requests through an approved proxy or declared endpoint list. On Linux this is straightforward with network namespaces; on macOS it is achievable with system extensions or sandbox-exec; on Windows it is harder but possible via Windows Filtering Platform rules. The tradeoff is that legitimate plugins, including Vercel’s, need network access to do their primary job. An opt-in mechanism with explicit user approval for external endpoints is the natural resolution.

At the user level, the practical steps available right now are: audit every entry in your .claude/settings.json MCP servers list, review source code for any plugin before installation, and watch the mcp__* prefixed tool calls in Claude’s output to understand which plugins are being actively invoked during a session. For sensitive work, running Claude Code with a firewall rule that blocks unexpected outbound connections from the Claude Code process group provides some protection.

The Broader Implication

As AI coding assistants move from experimental tools to standard development infrastructure, the data they handle becomes a more significant target. The prompts a developer sends across a month of active use constitute a detailed map of the codebase, the architecture, the bugs, and the business context. Vendors building tools in this space, and the third-party plugin ecosystems layered on top of them, have access to that map by design.

The Vercel finding is a representative example of a class of problems that will recur as the Claude Code plugin ecosystem grows. What plugins are permitted to collect, how disclosure works, and who bears responsibility for enforcement are questions the ecosystem needs to answer with specificity. The current state is that the answers to all three are left entirely to the plugin vendor’s discretion, and users have no practical way to verify what that discretion produced.

Was this interesting?