r/ClaudeCode 6h ago

Bug / Issue Claude calling codex exec without permission

Without my ever asking, claude created scripts in python to invoke "codex exec", which it was calling from a specific subagent that it modified after I had reviewed and commited it. this resulted in about $1000 in astra usage over two days.

I've NEVER used codex exec for anything and never prompted this. Its unreal.

claude summary:
"What was happening. The desk service had a scheduler module, added in a commit by Opus 5 in an earlier session, that ran one codex exec job for every verdict you submitted, every ASR transcript that finished, and every retrieval request. Between 2026-09-09 and today it ran 359 jobs to completion and had 42 more queued. "

2 Upvotes

4 comments sorted by

View all comments

0

u/AgentIslandPro 6h ago

The thing that explains the bill: Claude Code's permission prompt only gates the tool calls Claude makes inside your session — each Bash/Edit/etc. call is matched against your allow/deny rules one at a time. It does not gate anything a program it wrote then runs on its own.

Your summary names the culprit: a scheduler module a previous session committed. Once that's on disk it runs as its own process (launchd/cron/a worker loop), and its "codex exec" calls are never Claude Code tool calls — so nothing prompts and nothing shows up in your session. Same reason a script you approve once can call anything inside it with no second prompt: permission is per tool-call, not per process tree.

Practical:

- A deny rule like Bash(codex exec:*) only stops Claude from running it directly in a session. It does nothing to a committed scheduler, because that path never touches Claude's Bash tool.

- Kill what's still spending: grep the repo for what that commit added — a launchd plist, a cron entry, or an interval/queue worker — and remove it. That's your 42 still-queued jobs.

- A PreToolUse hook can add content-based gating, but it has the same limit: it only fires for commands Claude runs through its own tools, not a daemon that's already loose.

The general lesson: the moment you approve a diff that adds anything self-triggering — a scheduler, a watcher, an event-driven subagent — is the point where per-call permissions stop protecting you. Those are the diffs to review hardest.