From d3943e894cb18de488890da2ccd4729838b8c878 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 25 Apr 2026 21:05:53 +0200 Subject: [PATCH] =?UTF-8?q?fix(agent):=20SECURITY=20=E2=80=94=20replace=20?= =?UTF-8?q?bypassPermissions=20with=20dontAsk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bypassPermissions ignores --allowed-tools entirely (per permission-modes.md docs). With it, the model could call Bash, Write, Edit, Read, etc. — confirmed by writing /tmp/owned.sh in a test. dontAsk is the correct production headless mode: auto-DENIES anything outside the --allowed-tools whitelist instead of prompting. Without this, our entire MCP whitelist was effectively useless. --- agent/claude_wrapper.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/agent/claude_wrapper.py b/agent/claude_wrapper.py index 05dd054f..338fb53b 100644 --- a/agent/claude_wrapper.py +++ b/agent/claude_wrapper.py @@ -104,9 +104,13 @@ async def ask_claude(message: str, session_id: str) -> ClaudeResult: "json", "--allowed-tools", allowed_tools, - # Auto-approve any tool that's in --allowed-tools. + # CRITICAL: dontAsk auto-DENIES anything outside --allowed-tools. + # Do NOT use bypassPermissions here — that mode ignores the whitelist + # entirely and lets the model call Bash/Write/Edit/etc. (verified + # the hard way: it wrote /tmp/owned.sh when prompted to). + # See https://code.claude.com/docs/en/permission-modes.md "--permission-mode", - "bypassPermissions", + "dontAsk", ] logger.info(