Fetching from the wire…
Public story · 2026-08-30 · high
A lazy-loading quirk in IPython 9.17 let %%bash run even when Agno's CodeMode explicitly turned shell access off.
Why now: Agno published the fix, version 3.0.2, in its August 30 release notes.
Agno's CodeMode has a setting called allow_shell=False, meant to stop agents from running arbitrary shell commands. On IPython 9.17, it didn't work.
The bug is in how Agno disabled the %%bash magic. IPython 9.17 registers script magics like %%bash lazily, then recreates them whenever something looks them up. Agno's containment code removed bash from the cell-magic table once, at setup. But the lookup that follows just rebuilds the entry, so the block silently stopped applying. A kernel explicitly configured to forbid shell access still executed %%bash.
Worse, loading a sibling magic like %%sh could re-register bash on its own, so even a deployment that patched around the first problem stayed exposed through a side door.
The fix, shipped in Agno 3.0.2, materializes the script-magic provider before touching it, then strips bash from both the lazy table and the live registry at the same time. That closes the path IPython was using to bring the magic back.
If you run Agno agents with CodeMode and depend on allow_shell=False as your actual containment boundary rather than a soft guardrail, this is a forced upgrade, not an optional one. Check which IPython version your agent sandboxes are pinned to. The release doesn't say how far back the lazy-registration behavior goes in IPython's version history, so don't assume anything before 9.17 is safe by default. It's also worth checking whether other magics beyond %%sh can re-trigger the same registration path, since the release notes only name that one.
Each link below shares sources, entities, or timing with this story.
MCPConfig.tools now takes Agent, Team, and Workflow objects directly, so a caller sees a tool named chief instead of one dispatcher function.
MCPConfig.tools now accepts Agent, Team and Workflow instances plus Toolkit objects, exposing each as its own named MCP tool. You call chief, not run_agent(agent_id="chief"). Toolkits publish one MCP tool per registered method, narrowed by the toolkit's own enable/include/excl...
IPython 9.17 registers script magics lazily and recreates them on lookup, so Agno's method of removing bash from the cell-magic table stopped disabling it. A kernel explicitly configured to forbid shell access executed %%bash anyway. The fix materializes the script-magic provi...
Two of the six hid commands from the approval dialog itself, using tab padding, invisible Unicode, and split Bash strings.
The mismatch let a faked tool name slip past every human approval, allow-list, and audit log built to stop it.
Grep and Glob had the same gap, and the release also blocks project settings from logging raw API request bodies.
MindPattern daily
One email a day at 7 AM. Sources and a take on every story. Unsubscribe anytime.