From 23eae56ee7ed4ab8b243b222eda040dab0d09180 Mon Sep 17 00:00:00 2001 From: Ian Jhumel Bautista Date: Sat, 11 Jul 2026 18:56:00 +0800 Subject: [PATCH] =?UTF-8?q?fix:=202026-07-11=20audit=20follow-up=20?= =?UTF-8?q?=E2=80=94=20AG2-004=20GroupChat=20anchor,=20subagent/pydantic/c?= =?UTF-8?q?rewai/vercel=20coverage=20gaps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AG2-004 now anchors on the GroupChat config object (max_round is a GroupChat-only param; the manager fired on every properly configured chat). CSDK-111 gains MultiEdit/NotebookEdit needles; new CSDK-112 flags subagent WebSearch grants. PYD-103 gains WebSearchTool. New CREW-109 flags FileWriterTool/FileWriteTool. VAI-006 gains anthropic.tools.textEditor; new VAI-009 flags provider web-search/urlContext tools. --- autogen/agent_safety.yaml | 20 +++++---- claude_sdk/subagent_safety.yaml | 48 +++++++++++++++++----- crewai/dangerous_tools.yaml | 36 +++++++++++++++-- pydantic_ai/agent_safety.yaml | 34 +++++++++------- vercel_ai/agent_safety.yaml | 72 +++++++++++++++++++++++++-------- 5 files changed, 157 insertions(+), 53 deletions(-) diff --git a/autogen/agent_safety.yaml b/autogen/agent_safety.yaml index 4f838ec..5791030 100644 --- a/autogen/agent_safety.yaml +++ b/autogen/agent_safety.yaml @@ -74,7 +74,7 @@ rules: the AutoGen executor. - id: AG2-004 - title: AutoGen GroupChatManager has no explicit max_round bound + title: AutoGen group chat has no explicit max_round bound severity: low confidence: 0.6 language: python @@ -82,8 +82,11 @@ rules: - autogen_group_chat_manager scope: agent match: - agent_kwarg_missing: - - max_round + all: + - agent_class: + - GroupChat + - agent_kwarg_missing: + - max_round explanation: > This group chat does not set max_round explicitly, so the speaker-selection loop falls back to AutoGen's built-in max_round default rather than running @@ -92,11 +95,14 @@ rules: back and forth, or a model that never emits the termination signal) still runs to the default ceiling, burning token budget, and when the participating agents wield side-effecting tools (file writes, shell, network) the same - mutation can be applied repeatedly up to that bound. + mutation can be applied repeatedly up to that bound. The check anchors on + the GroupChat config object — the only constructor that accepts max_round — + so a GroupChatManager wrapping a bounded GroupChat does not fire on the + manager. fix: > - Pass max_round= to GroupChat / GroupChatManager with a concrete cap sized to - the workflow (often 10–25). Pair it with a clear termination condition so the - chat ends on success rather than only on the round cap. + Pass max_round= to GroupChat(...) with a concrete cap sized to the workflow + (often 10–25). Pair it with a clear termination condition so the chat ends + on success rather than only on the round cap. - id: AG2-005 title: AutoGen AssistantAgent enables code execution on the LLM agent diff --git a/claude_sdk/subagent_safety.yaml b/claude_sdk/subagent_safety.yaml index 0d429c2..5bf73ef 100644 --- a/claude_sdk/subagent_safety.yaml +++ b/claude_sdk/subagent_safety.yaml @@ -36,17 +36,43 @@ rules: subagent_grants_tool: - Write - Edit + - MultiEdit + - NotebookEdit - WebFetch explanation: > - This subagent's frontmatter grants a filesystem-write (`Write`/`Edit`) or - web-fetch (`WebFetch`) built-in. Like Bash (CSDK-110), these widen the - blast radius of an autonomously-dispatched subagent: write tools let it - modify source, config, or the `.claude/` settings that govern it, and - WebFetch pulls attacker-controllable URL content back into the loop (a - prompt-injection and SSRF surface). A narrowly-scoped subagent rarely - needs them. + This subagent's frontmatter grants a filesystem-write + (`Write`/`Edit`/`MultiEdit`/`NotebookEdit`) or web-fetch (`WebFetch`) + built-in. Like Bash (CSDK-110), these widen the blast radius of an + autonomously-dispatched subagent: write tools let it modify source, + config, or the `.claude/` settings that govern it, and WebFetch pulls + attacker-controllable URL content back into the loop (a prompt-injection + and SSRF surface). A narrowly-scoped subagent rarely needs them. fix: > - Remove `Write`/`Edit`/`WebFetch` from the subagent's `tools:` list unless - the role genuinely requires them. For read/research roles prefer Read, - Grep, Glob; for fetching, gate with a PreToolUse hook that allowlists - hosts. + Remove the write and fetch built-ins from the subagent's `tools:` list + unless the role genuinely requires them. For read/research roles prefer + Read, Grep, Glob; for fetching, gate with a PreToolUse hook that + allowlists hosts. + + - id: CSDK-112 + title: Subagent granted the WebSearch tool + severity: medium + confidence: 0.8 + applies_to: + - claude_subagent + scope: subagent + match: + subagent_grants_tool: + - WebSearch + explanation: > + This subagent's frontmatter grants the built-in `WebSearch` tool, so + search-result content chosen by the model flows back into the subagent's + context. Search results are attacker-reachable text (anyone can publish a + page that ranks for a query the subagent is likely to make), which makes + the grant a prompt-injection channel into an autonomously-dispatched + worker — the same surface the agent-scope check flags on + AgentDefinition (CSDK-102), here declared in `.claude/agents/*.md`. + fix: > + Remove `WebSearch` from the subagent's `tools:` list unless the role is + genuinely research-oriented. If the subagent must search, keep its other + grants read-only so injected search content cannot escalate into writes + or shell, and treat its output as untrusted in the parent loop. diff --git a/crewai/dangerous_tools.yaml b/crewai/dangerous_tools.yaml index fd95693..f8c29d6 100644 --- a/crewai/dangerous_tools.yaml +++ b/crewai/dangerous_tools.yaml @@ -4,9 +4,9 @@ policy: category: crewai description: > Flags CrewAI agents wired with high-risk crewai_tools built-ins: an - unconstrained file reader, and the web-fetching / RAG tools that retrieve - model-chosen URLs. Both are vectors in CrewAI's published file-read and SSRF - advisories. + unconstrained file reader, the file-writing tools, and the web-fetching / + RAG tools that retrieve model-chosen URLs. The reader and fetchers are + vectors in CrewAI's published file-read and SSRF advisories. rules: - id: CREW-106 @@ -71,3 +71,33 @@ rules: raw model-supplied URLs. Treat any retrieved content as untrusted input — keep it out of the system prompt and do not let it silently expand the agent's tool permissions. + + - id: CREW-109 + title: CrewAI agent wires a model-driven file-writing tool + severity: high + confidence: 0.75 + language: python + applies_to: + - crewai_agent + scope: agent + match: + agent_uses_hosted_tool_class: + - FileWriterTool + - FileWriteTool + explanation: > + This agent wires a crewai_tools file-writing built-in (FileWriterTool / + FileWriteTool). Both the target path and the content are supplied by the + model at call time, so a prompt injection can write attacker-chosen bytes + to any path the agent process can reach: overwrite application source or + config, drop a malicious script where something else will execute it + (cron, CI, an imported module), or plant credentials files. Write access + is strictly more dangerous than the unconstrained read this pack already + flags (CREW-106) — a write turns injected text into persistent state and, + transitively, into code execution. + fix: > + Remove the file-writing tool unless the workflow genuinely produces files. + If it must write, wrap it in a custom tool that pins the output directory, + validates the filename against an allow-list, resolves symlinks, rejects + any path escaping the intended root, and never writes to locations that + are executed or imported. Run the agent with least-privilege filesystem + permissions so even a successful injection cannot touch source or config. diff --git a/pydantic_ai/agent_safety.yaml b/pydantic_ai/agent_safety.yaml index 0127bbc..a10d842 100644 --- a/pydantic_ai/agent_safety.yaml +++ b/pydantic_ai/agent_safety.yaml @@ -65,7 +65,7 @@ rules: explicit human approval rather than exposing a model-invokable code runner. - id: PYD-103 - title: Pydantic AI agent wires a model-driven URL-fetching native tool + title: Pydantic AI agent wires a model-driven web-fetching or search native tool severity: medium confidence: 0.75 language: python @@ -76,23 +76,27 @@ rules: agent_uses_hosted_tool_class: - WebFetchTool - UrlContextTool + - WebSearchTool explanation: > - This agent wires a native URL-fetching tool (WebFetchTool or UrlContextTool) - that retrieves model-chosen URLs. The model controls the destination, so a - prompt injection can point it at internal services, the cloud metadata - endpoint (169.254.169.254), or localhost admin ports the agent host can - reach — a server-side request forgery surface — and can also exfiltrate - retrieved or in-context data to an attacker-controlled URL. Pydantic AI's - built-in fetchers have already needed SSRF hardening (CVE-2026-46678, - CVE-2026-25580), so enabling one without network egress controls reintroduces - that exposure. + This agent wires a native web-retrieval tool (WebFetchTool, UrlContextTool, + or WebSearchTool) whose destination or query the model controls. For the + URL fetchers, a prompt injection can point the request at internal + services, the cloud metadata endpoint (169.254.169.254), or localhost + admin ports the agent host can reach — a server-side request forgery + surface — and can also exfiltrate retrieved or in-context data to an + attacker-controlled URL. For WebSearchTool, the query itself is an + exfiltration channel and the returned results are attacker-reachable text + that re-enters the context as a second-order prompt-injection channel. + Pydantic AI's built-in fetchers have already needed SSRF hardening + (CVE-2026-46678, CVE-2026-25580), so enabling one without network egress + controls reintroduces that exposure. fix: > - Only enable a native fetch tool when the agent genuinely needs open web - access, and put network egress controls around the agent process: an - allow-list of permitted hosts, blocked private/link-local IP ranges, and a - proxy that rejects requests to internal addresses. Prefer a purpose-built + Only enable a native fetch or search tool when the agent genuinely needs + open web access, and put network egress controls around the agent process: + an allow-list of permitted hosts, blocked private/link-local IP ranges, and + a proxy that rejects requests to internal addresses. Prefer a purpose-built tool that fetches from a fixed, vetted set of endpoints over an open URL - fetcher. + fetcher, and treat retrieved or searched content as untrusted input. - id: PYD-105 title: Pydantic AI agent retries with the exhaustive end strategy diff --git a/vercel_ai/agent_safety.yaml b/vercel_ai/agent_safety.yaml index 2240771..c49eb56 100644 --- a/vercel_ai/agent_safety.yaml +++ b/vercel_ai/agent_safety.yaml @@ -6,13 +6,14 @@ policy: Agent-scope safety rules for Vercel AI SDK agents — the generateText / streamText / generateObject / streamObject tool-loop calls and the ToolLoopAgent class. These flag agents wired with provider tools that hand - the model shell, computer-control, or code-execution reach, and agents whose - tool loop has no bound, the two ways a Vercel agent turns a prompt injection - into runaway or arbitrary execution. + the model shell, computer-control, file-editing, or code-execution reach, + agents wired with provider tools that retrieve model-chosen web content, + and agents whose tool loop has no bound — the ways a Vercel agent turns a + prompt injection into runaway execution or data exfiltration. rules: - id: VAI-006 - title: Vercel AI agent wires a provider shell / computer / code-execution tool + title: Vercel AI agent wires a provider shell / computer / file-editing / code-execution tool severity: high confidence: 0.85 language: typescript @@ -23,6 +24,7 @@ rules: agent_uses_hosted_tool_class: - anthropic.tools.bash - anthropic.tools.computer + - anthropic.tools.textEditor - anthropic.tools.codeExecution - openai.tools.localShell - openai.tools.computerUsePreview @@ -30,20 +32,22 @@ rules: - google.tools.codeExecution explanation: > This agent's tools record includes a Vercel-provider tool that gives the - model shell, full computer control, or a code interpreter — anthropic's - bash / computer / codeExecution, openai's localShell / computerUsePreview / - codeInterpreter, or google's codeExecution. The Vercel AI SDK ships and - markets these provider tools as first-class, so wiring one is a single line - that hands a model-driven loop direct execution on the host or sandbox. - Because the agent's prompts and prior tool outputs are model-reachable, a - prompt injection has a direct path to running attacker-chosen commands or - code with the agent's privileges. + model shell, full computer control, host file editing, or a code + interpreter — anthropic's bash / computer / textEditor / codeExecution, + openai's localShell / computerUsePreview / codeInterpreter, or google's + codeExecution. The Vercel AI SDK ships and markets these provider tools as + first-class, so wiring one is a single line that hands a model-driven loop + direct execution or file mutation on the host or sandbox. Because the + agent's prompts and prior tool outputs are model-reachable, a prompt + injection has a direct path to running attacker-chosen commands or code — + or writing attacker-chosen file content — with the agent's privileges. fix: > - Drop the provider execution tool unless the workflow truly requires it. If - it is essential, run it against an isolated, ephemeral sandbox with no - credentials, no private-network reach, and a hard timeout; constrain which - commands or code may run; and gate every invocation behind an explicit - human approval rather than letting the tool loop call it autonomously. + Drop the provider execution or editing tool unless the workflow truly + requires it. If it is essential, run it against an isolated, ephemeral + sandbox with no credentials, no private-network reach, and a hard timeout; + constrain which commands, code, or paths it may touch; and gate every + invocation behind an explicit human approval rather than letting the tool + loop call it autonomously. - id: VAI-007 title: Vercel AI agent tool loop has no explicit step bound @@ -111,3 +115,37 @@ rules: a call is genuinely mandatory. Keep shell / computer / code-execution tools out of any agent that forces a tool call, and gate their use behind an explicit approval. + + - id: VAI-009 + title: Vercel AI agent wires a provider tool that retrieves model-chosen web content + severity: medium + confidence: 0.7 + language: typescript + applies_to: + - vercel_ai_agent + scope: agent + match: + agent_uses_hosted_tool_class: + - anthropic.tools.webSearch + - openai.tools.webSearch + - openai.tools.webSearchPreview + - google.tools.googleSearch + - google.tools.urlContext + explanation: > + This agent's tools record includes a Vercel-provider tool that retrieves + web content the model chooses — anthropic's webSearch, openai's webSearch / + webSearchPreview, or google's googleSearch / urlContext. The model controls + the query or URL, so an injected instruction can steer retrieval toward + attacker-published pages, and the query string itself is a channel for + exfiltrating in-context data. The retrieved content then re-enters the + conversation as untrusted text, giving the fetched site a second-order + prompt-injection channel into the agent — the same surface the OpenAI, + Google ADK, CrewAI, and Pydantic AI packs flag on their web-retrieval + built-ins. + fix: > + Only wire a provider search or URL-context tool when the agent genuinely + needs open web access. Treat everything it returns as untrusted input: + keep it out of the system prompt, do not let it expand tool permissions, + and pair it with an output check before retrieved text can influence + side-effecting tools. For urlContext, constrain candidate URLs to an + allow-list of hosts rather than passing raw model-supplied links.