If you believe you've found a security issue in Bonsai, please do not open a public GitHub issue. Instead, email 1bonsegnaferdinando@gmail.com with:
- A description of the issue and the affected version
- Steps to reproduce
- Your assessment of impact
I'll acknowledge within 72 hours and aim to ship a fix within 7 days for high-severity issues. After the fix is released, you're welcome to disclose publicly; I'll credit you in the changelog unless you'd rather stay anonymous.
Bonsai is a Claude Code plugin that executes shell scripts in your local environment as part of normal operation. This makes the threat model worth being explicit about.
- Read your Claude Code session transcript: the Stop hook slices the transcript to its last ~200 lines (configurable via
transcript_tail_lines) and the gardener reads that slice directly with theReadtool. - Read files in your project directory to gather evidence (and the
git diff HEAD, excluding.claude/bonsai/, passed to it as context). - Optionally run read-only
gitcommands when a.git/directory exists. - Write to
${CLAUDE_PROJECT_DIR}/.claude/bonsai/(branch files, INDEX.md, state.json, trimmed.md). - Write to
${CLAUDE_PLUGIN_DATA}/(whitelist, global config, quota counters, mute state, logs, transcript slices, per-session judge scratch dir). - Run a cheap second model (
claude -p --model haiku) over its own candidate observations to dedup/calibrate them before writing (the judge pass).
- Edit any file outside
.claude/bonsai/. The gardener's frontmatter declares onlyBash, Read, Grep, Glob, Write— noEdit. Bash is restricted to read-only commands in the gardener's system prompt; Write is restricted to the bonsai directory. - Make any network call. No
WebSearch, noWebFetchin the gardener's tool list. - Run arbitrary code suggested by the LLM. The gardener only writes observations to files; it never executes them. The user reads
INDEX.md//bonsai:listand decides what to act on. - Spawn sub-subagents. The gardener's tool list does not include the
Tasktool, so it cannot dispatch further agents.
Slash commands (/bonsai:done <id>, /bonsai:config <key> <value>, …) pass their arguments into a shell invocation. The argument placeholders are quoted in each commands/*.md so shell metacharacters in an argument are treated as data, not code. Note that Claude Code itself interpolates these placeholders textually before the shell parses them (upstream behavior), so treat command arguments you type as trusted input.
- Silent failure on the hook path. Any error in
hooks/stop.shis trapped, logged, and the script exits 0. This protects the user's session but means a bug could silently disable observation. Inspect${CLAUDE_PLUGIN_DATA}/logs/bonsai-errors.logif you suspect Bonsai is misbehaving. - Corrupt JSON in state files. Every read function defends against corruption and returns safe defaults. Write functions refuse to overwrite a known-corrupt file (
/bonsai:configis the user-facing example;bonsai_json_writeis the underlying primitive). - Concurrent writes. Per-project state writes use
mktemp + mvfor atomicity. The whitelist add path has a small TOCTOU window for concurrent/bonsai:startinvocations on the same project; this is documented in the source and considered acceptable for v1.
${CLAUDE_PLUGIN_DATA}/logs/bonsai-errors.log— every silent failure path logs here.${CLAUDE_PROJECT_DIR}/.claude/bonsai/INDEX.md— confirms what observations have been emitted./bonsai:status— surfaces last run, quota, mute state, last error.
Only the latest released version receives security fixes. Pre-1.0, expect rapid iteration. From 1.0 onward, the latest minor version on the latest major line is supported.
| Version | Supported |
|---|---|
| Latest release (0.5.x) | ✅ |
| Older releases | ❌ |