Skip to content

security: keep BUZZ_PRIVATE_KEY out of agent-controlled processes #2883

Description

@benthecarman

Summary

buzz-acp currently includes the agent identity's BUZZ_PRIVATE_KEY in the MCP server configuration. buzz-dev-mcp then intentionally inherits that variable into every process started by its shell tool so the bundled buzz CLI can authenticate.

This makes the raw signing key available to model-controlled commands. For example, a shell command can read BUZZ_PRIVATE_KEY directly from its environment. With network access, prompt injection could disclose the key and allow an attacker to impersonate the agent outside Buzz.

Relevant paths:

  • crates/buzz-acp/src/lib.rs (build_mcp_servers) serializes BUZZ_PRIVATE_KEY into mcpServers.env.
  • crates/buzz-dev-mcp/src/shell.rs intentionally inherits BUZZ_PRIVATE_KEY into shell children.
  • crates/buzz-dev-mcp/src/shim.rs documents that inheritance for the bundled CLI.

Desired security boundary

The ACP harness can retain the private key because it already uses the agent identity for relay subscriptions and publishing. The third-party agent runtime, model-visible tool configuration, arbitrary shell commands, and shell child processes should not receive the raw key.

A dedicated low-privilege agent identity remains useful defense in depth, but it should not be the only protection against key disclosure.

Proposed direction

  1. Keep the private key in buzz-acp or another harness-owned signer/publisher component.
  2. Remove BUZZ_PRIVATE_KEY from the MCP configuration sent through session/new and from buzz-dev-mcp shell-child inheritance.
  3. Expose a narrowly scoped MCP tool for publishing a Buzz message or reply. The tool should accept typed message fields, validate them, sign and submit internally, and return the relay write result.
  4. Do not expose a generic sign(payload) tool or return raw signatures. That would hide the key bytes but create a signing oracle with nearly equivalent authority.
  5. Give any MCP-side helper only an opaque, session-bound capability to the harness-owned publisher, not the private key. The capability should authorize only the typed operation and expire when the session ends.
  6. Replace authenticated shell-based Buzz operations with typed, least-authority tools as needed. Unsupported CLI operations should fail without credentials rather than silently restoring key inheritance.

There was previously a buzz_send_message tool, removed in commit a30d52515 in favor of the shell-based CLI. Its typed interface may be reusable, but its old implementation spawned the CLI and depended on inherited credentials, so restoring it unchanged would not fix the boundary.

Acceptance criteria

  • BUZZ_PRIVATE_KEY is absent from ACP mcpServers.env and from all model-controlled process environments.
  • A shell tool call cannot recover the key with environment inspection.
  • The agent can publish a new message and a threaded reply through a typed tool.
  • The tool cannot sign or return arbitrary caller-provided payloads.
  • Invalid channel IDs, event IDs, empty/oversized content, relay errors, and expired session capabilities produce structured errors without secret material.
  • Tests assert both successful message publication and the absence of the key from MCP configuration and shell-child environments.
  • Agent prompts and documentation no longer instruct the model to use BUZZ_PRIVATE_KEY or shell-based buzz messages send.

Additional threat-model note

This change prevents direct disclosure through the supported agent/tool interface. Protecting against an arbitrary hostile process running as the same OS user may require stronger process isolation or a remote/keychain-backed signer and can be handled separately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions