{"slug": "i-scanned-my-ai-agent-framework-for-destructive-consequential-actions-and-wow", "title": "I scanned my AI agent framework for destructive/consequential actions, and wow", "summary": "A static analysis of 25 AI agent frameworks (23,476 files) found 30 instances where a model-controlled parameter reaches a consequential action with no authorization check, according to a research note published July 2026. The study, which pinned repositories by SHA for reproducibility, identified 12 false positives in its own scanner and fixed them before publication. The findings include 15 network egress cases, 7 file writes, 3 shell executions, 2 message sends, 2 file deletions, and 1 SQL execution, with crewAIInc/crewAI having the most findings at 12.", "body_md": "Research noteJuly 2026Apache 2.0\n\n# Your agent can already do things *nobody authorised*.\n\nWe scanned 25 AI agent frameworks — 23,476 files — looking for one specific thing: a consequential action that a model can reach, with a parameter the model controls, and no authorisation check on the path. We found 30. We also found 12 false positives in our own scanner, and fixed them before publishing this.\n\n**25** repos, pinned by SHA\n\n**23,476** files analysed\n\n**30** findings, hand-triaged\n\n**0** in control repos\n\nThe gap\n\n## Validation is not authorisation.\n\nMost agent tools check that a request is well-formed. Far fewer check that *this* caller is permitted to perform *this exact action*, right now — at the point where the side effect actually happens.\n\nThat distinction is invisible in a code review, because both look like a guard. It is the difference between a tool that refuses an unauthorised refund and one that processes it correctly.\n\nThe scanner looks for exactly one shape: a model-controlled parameter reaching a recognised consequential sink, with no check that dominates every path to it.\n\nThe study25 repositories, immutable SHAs\n\n## Where the findings actually were.\n\nEvery repository is pinned by commit hash so the result is reproducible. Five non-agent control repositories were included deliberately: any finding in those is a precision failure by definition. There were none.\n\n| Repository | Class | Findings |\n|---|---|---|\n| crewAIInc/crewAI | framework | 12 |\n| TransformerOptimus/SuperAGI | application | 6 |\n| FoundationAgents/MetaGPT | application | 5 |\n| microsoft/semantic-kernel | framework | 3 |\n| agno-agi/agno | framework | 2 |\n| modelcontextprotocol/servers | MCP server | 1 |\n| modelcontextprotocol/python-sdk | MCP server | 1 |\n| requests · flask · fastapi · click · rich | control | 0 |\n\n| What the action was | Count |\n|---|---|\n| Network egress with model-controlled destination | 15 |\n| File write to a model-controlled path | 7 |\n| Shell execution | 3 |\n| Message send to a model-controlled recipient | 2 |\n| File deletion | 2 |\n| SQL execution with a model-controlled statement | 1 |\n\nWhat we got wrongand found ourselves\n\n## The first run of this study was 81% precise.\n\nTwelve of sixty-three findings were wrong. We publish that because a scanner claiming perfect precision has either not been measured or is not being honest, and because the failure classes are more useful to you than the successes.\n\n-\n**A Kubernetes rule that matched a search client** The pattern\n\n`client.*.create`\n\nwas loose enough to match Elasticsearch and vector-store clients. It fired at HIGH severity in two well-known repositories. Constrained to genuine Kubernetes surfaces. -\n**A SQL rule that caught the safe case and missed the dangerous one** It matched the literal string\n\n`execute(\"DROP TABLE …\")`\n\nbut not`execute(query)`\n\n— where the model controls the statement. It was detecting hardcoded SQL and ignoring caller-controlled SQL. Now matches the sink, not the text. -\n**A bulk-deletion call that was never in the vocabulary**`s3.delete_objects`\n\n— deleting many objects at once — simply was not a recognised sink. Added, with the exact source line kept as a regression test.\n\nEach fix carries a permanent regression fixture, and CI now fails if any finding in the corpus is untriaged or triaged as a false positive. The 30/30 is enforced, not asserted.\n\nLimits\n\n## What this cannot see.\n\nStatic analysis of guard soundness is undecidable in the general case. Rather than claim coverage we cannot demonstrate, here is what is verified against real code and what is not.\n\n| Agent architecture | Status |\n|---|---|\nMCP `@mcp.tool()` | COVERED |\nLangChain `@tool` / BaseTool | COVERED |\nOpenAI `@function_tool` | PARTIAL |\n| Custom agent loops | NOT COVERED |\n| Action/observation dispatchers | NOT COVERED |\n\n**A finding is not a vulnerability**\n\nThe scanner establishes that a model-controlled parameter reaches a consequential action with no dominating authority check *in the analysed path*. It does not establish that the agent is externally reachable, that no guard exists elsewhere in the system, or that the action is exploitable.\n\n**Custom agent loops were tried and rejected**\n\nDetecting agents that run whatever the model returns, with no framework decorator, produced 10 false positives out of 10 candidates. The signal decomposes into “this module talks to an LLM” and “this function runs what it was passed” — which describes most of an agent framework. Recorded as a negative result rather than shipped.\n\n**Cryptographic binding is invisible to it**\n\nWhen authority is carried inside a signed proof object, the binding between the authorisation and the specific action is real but not visible at the call site. A static scanner cannot verify it. That is an argument for checking at runtime, not for trusting the scan.\n\nRun itno account, no signup, no network calls\n\n## Ten seconds on your own code.\n\nZero runtime dependencies. Nothing is uploaded. If it finds nothing, it tells you precisely what that does and does not mean.\n\n`$ pipx run actenon-scan scan .`", "url": "https://wpnews.pro/news/i-scanned-my-ai-agent-framework-for-destructive-consequential-actions-and-wow", "canonical_source": "https://www.actenon.com/", "published_at": "2026-07-26 00:58:07+00:00", "updated_at": "2026-07-26 01:22:17.455687+00:00", "lang": "en", "topics": ["ai-safety", "ai-agents", "ai-research"], "entities": ["crewAIInc/crewAI", "TransformerOptimus/SuperAGI", "FoundationAgents/MetaGPT", "microsoft/semantic-kernel", "agno-agi/agno", "modelcontextprotocol/servers", "modelcontextprotocol/python-sdk"], "alternates": {"html": "https://wpnews.pro/news/i-scanned-my-ai-agent-framework-for-destructive-consequential-actions-and-wow", "markdown": "https://wpnews.pro/news/i-scanned-my-ai-agent-framework-for-destructive-consequential-actions-and-wow.md", "text": "https://wpnews.pro/news/i-scanned-my-ai-agent-framework-for-destructive-consequential-actions-and-wow.txt", "jsonld": "https://wpnews.pro/news/i-scanned-my-ai-agent-framework-for-destructive-consequential-actions-and-wow.jsonld"}}