block / block/buzz

macOS pgrep/ps can read every managed agent's BUZZ_PRIVATE_KEY (nsec in KERN_PROCARGS2 environ)

Open
#6,973 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Summary

On macOS, `pgrep -fl` / `ps` can read every managed agent's `BUZZ_PRIVATE_KEY` (nsec) because Desktop injects it into the `buzz-acp` child environment and Darwin `KERN_PROCARGS2` concatenates environ after argv. Grandchildren (`npm`, `node`, `vite preview`, etc.) inherit the key. Any same-UID process on the machine can impersonate any other managed agent.

This is inherited environment, not argv. `argv` does not contain the nsec; `pgrep -fl` still prints it because it dumps the full `KERN_PROCARGS2` buffer.

## Why NIP-GS's current wording is not enough

[NIP-GS "Key Exposure via Environment Variables"](https://github.com/block/buzz/blob/main/docs/nips/NIP-GS.md) documents Linux `/proc//environ` and calls the model acceptable for "agent processes running in a controlled environment (e.g., spawned by a desktop app with process-scoped env vars)."

A Desktop nest with many managed agents on one Mac is not a controlled environment in that sense: every seat runs as the same OS user. One agent (or any npm script, postinstall, or leftover `vite preview`) can `pgrep -fl buzz-acp` and obtain every other seat's signing key.

macOS is not mentioned. `pgrep -fl` is the accidental disclosure path people actually hit — it looks like the secret was passed on the command line even when it was not.

## Reproduction (no secret in the report)

1. Run a managed agent on macOS Desktop.
2. From another same-user shell: `pgrep -fl buzz-acp` (or `pgrep -fl vite` if an agent left a preview server running).
3. Observe `BUZZ_PRIVATE_KEY=nsec1…` in the listed "command" text.
4. Confirm with `KERN_PROCARGS2` that the nsec is in **environ**, not `argv` (`argc` strings do not contain it; the env block after the NUL padding does).

Do not paste the nsec. Redact before sharing `ps` output.

## Expected

- Agent identity should not be readable from the process table of sibling same-UID processes.
- At minimum, long-lived grandchildren should not inherit `BUZZ_PRIVATE_KEY`.
- Docs should name Darwin `KERN_PROCARGS2` / `pgrep -fl` alongside `/proc//environ`.

## Observed spawn site

`desktop/src-tauri/src/managed_agents/runtime.rs` — `command.env("BUZZ_PRIVATE_KEY", &record.private_key_nsec);` on the `buzz-acp` child. Reserved-env stripping correctly blocks *user* env from setting that key; Desktop still injects it itself, which is the leak.

## Suggested direction (not a patch)

- Prefer a fd / unix-socket / one-shot helper for identity so the nsec is not in `environ` of the ACP process or its grandchildren.
- If env injection stays: drop `BUZZ_PRIVATE_KEY` from the environment before the inner agent runtime execs tools, or document a required `env -u BUZZ_PRIVATE_KEY` around long-lived children.
- Treat sibling managed agents on the same UID as the threat model, not only "the process itself and its children."

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.