From 754fbf1fb5e3eaaaee790d016f98944e04678f7e Mon Sep 17 00:00:00 2001 From: Phoenix Wang Date: Mon, 24 Aug 2026 14:34:59 -0400 Subject: [PATCH 1/2] docs(mcp): add MCP-023 PHP untyped-params rationale Close the documented PHP fast-follow: type hints are optional, so unconstrained MCP input schemas are a real signal. Co-authored-by: Cursor --- POLICY_INDEX.md | 155 +++++++++++++++-------------- docs/Policy/mcp/tool_definition.md | 54 ++++++++-- mcp/POLICY_INDEX.md | 3 +- 3 files changed, 126 insertions(+), 86 deletions(-) diff --git a/POLICY_INDEX.md b/POLICY_INDEX.md index 8e650ea..3a600c5 100644 --- a/POLICY_INDEX.md +++ b/POLICY_INDEX.md @@ -43,13 +43,13 @@ Users can contribute their own policies by: | Claude Agent SDK | 17 | 12 | 3 | 3 | 35 | [claude_sdk/POLICY_INDEX.md](claude_sdk/POLICY_INDEX.md) | | OpenAI Agents SDK | 21 | 9 | 0 | 2 | 32 | [openai_sdk/POLICY_INDEX.md](openai_sdk/POLICY_INDEX.md) | | Google ADK | 14 | 11 | 0 | 1 | 26 | [google_adk/POLICY_INDEX.md](google_adk/POLICY_INDEX.md) | -| Model Context Protocol | 22 | 0 | 0 | 0 | 22 | [mcp/POLICY_INDEX.md](mcp/POLICY_INDEX.md) | +| Model Context Protocol | 23 | 0 | 0 | 0 | 23 | [mcp/POLICY_INDEX.md](mcp/POLICY_INDEX.md) | | LangChain / LangGraph | 11 | 3 | 0 | 1 | 15 | [langchain/POLICY_INDEX.md](langchain/POLICY_INDEX.md) | | CrewAI | 7 | 7 | 0 | 1 | 15 | [crewai/POLICY_INDEX.md](crewai/POLICY_INDEX.md) | | AutoGen / AG2 | 6 | 5 | 0 | 1 | 12 | [autogen/POLICY_INDEX.md](autogen/POLICY_INDEX.md) | | Vercel AI SDK | 6 | 4 | 0 | 1 | 11 | [vercel_ai/POLICY_INDEX.md](vercel_ai/POLICY_INDEX.md) | | Pydantic AI | 7 | 4 | 0 | 1 | 12 | [pydantic_ai/POLICY_INDEX.md](pydantic_ai/POLICY_INDEX.md) | -| **All** | **111** | **55** | **3** | **11** | **180** | | +| **All** | **112** | **55** | **3** | **11** | **181** | | ## All rules @@ -170,78 +170,79 @@ Users can contribute their own policies by: | 113 | MCP-020 | MCP | tool | mcp_tool | Ambiguous PHP MCP tool name | low | 0.85 | 12.8 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 114 | MCP-021 | MCP | tool | mcp_tool | Rust MCP tool has no description | low | 0.85 | 12.8 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 115 | MCP-022 | MCP | tool | mcp_tool | Ambiguous Rust MCP tool name | low | 0.85 | 12.8 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | -| 116 | LC-001 | LangChain | tool | langchain_tool | LangChain tool has no description | low | 0.80 | 12.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | -| 117 | LC-002 | LangChain | tool | langchain_tool | LangChain tool parameters are not type-annotated | medium | 0.85 | 34.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | -| 118 | LC-003 | LangChain | tool | langchain_tool | LangChain tool body spawns a subprocess | high | 0.85 | 59.5 | [langchain/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/shell_safety.yaml) | -| 119 | LC-004 | LangChain | tool | langchain_tool | LangChain tool body evaluates dynamic code | high | 0.85 | 59.5 | [langchain/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/code_execution.yaml) | -| 120 | LC-005 | LangChain | tool | langchain_tool | LangChain tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [langchain/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/ssrf.yaml) | -| 121 | LC-006 | LangChain | tool | langchain_tool | LangChain tool returns its output directly, bypassing the model | medium | 0.80 | 32.0 | [langchain/tool_behavior.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_behavior.yaml) | -| 122 | LC-010 | LangChain | tool | langchain_tool | TypeScript LangChain tool has no description | low | 0.80 | 12.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | -| 123 | LC-011 | LangChain | tool | langchain_tool | TypeScript LangChain tool body spawns a subprocess | high | 0.85 | 59.5 | [langchain/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/shell_safety.yaml) | -| 124 | LC-012 | LangChain | tool | langchain_tool | TypeScript LangChain tool evaluates dynamic code | high | 0.85 | 59.5 | [langchain/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/code_execution.yaml) | -| 125 | LC-013 | LangChain | tool | langchain_tool | TypeScript LangChain tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [langchain/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/ssrf.yaml) | -| 126 | LC-014 | LangChain | tool | langchain_tool | TypeScript LangChain tool returns its output directly, bypassing the model | medium | 0.80 | 32.0 | [langchain/tool_behavior.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_behavior.yaml) | -| 127 | LC-101 | LangChain | agent | langchain_agent, langchain_agent_executor, langchain_state_graph | LangChain agent wires a code-execution or shell built-in tool | high | 0.85 | 59.5 | [langchain/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/agent_safety.yaml) | -| 128 | LC-102 | LangChain | agent | langchain_agent_executor | LangChain AgentExecutor has no explicit max_iterations limit | low | 0.60 | 9.0 | [langchain/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/agent_safety.yaml) | -| 129 | LC-111 | LangChain | agent | langchain_agent_executor | TypeScript LangChain AgentExecutor has no explicit maxIterations limit | low | 0.60 | 9.0 | [langchain/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/agent_safety.yaml) | -| 130 | LC-201 | LangChain | repo | langchain | LangChain project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [langchain/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/repo_hygiene.yaml) | -| 131 | CREW-001 | CrewAI | tool | crewai_tool | CrewAI tool has no description | low | 0.90 | 13.5 | [crewai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/tool_definition.yaml) | -| 132 | CREW-002 | CrewAI | tool | crewai_tool | CrewAI tool parameters are not type-annotated | medium | 0.85 | 34.0 | [crewai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/tool_definition.yaml) | -| 133 | CREW-003 | CrewAI | tool | crewai_tool | CrewAI tool body evaluates dynamic code | high | 0.85 | 59.5 | [crewai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/code_execution.yaml) | -| 134 | CREW-004 | CrewAI | tool | crewai_tool | CrewAI tool body spawns a subprocess | high | 0.85 | 59.5 | [crewai/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/shell_safety.yaml) | -| 135 | CREW-005 | CrewAI | tool | crewai_tool | CrewAI tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [crewai/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/ssrf.yaml) | -| 136 | CREW-006 | CrewAI | tool | crewai_tool | Mutating CrewAI tool has no idempotency key | medium | 0.55 | 22.0 | [crewai/idempotency.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/idempotency.yaml) | -| 137 | CREW-101 | CrewAI | agent | crewai_agent | CrewAI agent enables built-in code execution | high | 0.90 | 63.0 | [crewai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/agent_safety.yaml) | -| 138 | CREW-102 | CrewAI | agent | crewai_agent | CrewAI agent runs code execution in unsafe mode | high | 0.90 | 63.0 | [crewai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/agent_safety.yaml) | -| 139 | CREW-103 | CrewAI | agent | crewai_agent | CrewAI agent wires the code-interpreter built-in tool | high | 0.85 | 59.5 | [crewai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/code_execution.yaml) | -| 140 | CREW-104 | CrewAI | agent | crewai_agent | CrewAI agent allows delegation to peer agents | medium | 0.75 | 30.0 | [crewai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/agent_safety.yaml) | -| 141 | CREW-106 | CrewAI | agent | crewai_agent | CrewAI agent grants an unconstrained FileReadTool | high | 0.70 | 49.0 | [crewai/dangerous_tools.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/dangerous_tools.yaml) | -| 142 | CREW-107 | CrewAI | agent | crewai_agent | CrewAI agent wires a tool that fetches model-chosen URLs | medium | 0.70 | 28.0 | [crewai/dangerous_tools.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/dangerous_tools.yaml) | -| 143 | CREW-108 | CrewAI | tool | crewai_tool | CrewAI tool returns its output as the final answer | medium | 0.60 | 24.0 | [crewai/tool_behavior.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/tool_behavior.yaml) | -| 144 | CREW-109 | CrewAI | agent | crewai_agent | CrewAI agent wires a model-driven file-writing tool | high | 0.75 | 52.5 | [crewai/dangerous_tools.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/dangerous_tools.yaml) | -| 145 | CREW-201 | CrewAI | repo | crewai | CrewAI project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [crewai/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/repo_hygiene.yaml) | -| 146 | AG2-001 | AutoGen | agent | autogen_conversable_agent, autogen_user_proxy_agent | AutoGen executor runs code on the host without Docker | high | 0.90 | 63.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | -| 147 | AG2-002 | AutoGen | agent | autogen_conversable_agent, autogen_user_proxy_agent | AutoGen executor runs code with no human review (human_input_mode=NEVER) | high | 0.85 | 59.5 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | -| 148 | AG2-004 | AutoGen | agent | autogen_group_chat_manager | AutoGen group chat has no explicit max_round bound | low | 0.60 | 9.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | -| 149 | AG2-005 | AutoGen | agent | autogen_assistant_agent | AutoGen AssistantAgent enables code execution on the LLM agent | medium | 0.70 | 28.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | -| 150 | AG2-006 | AutoGen | agent | autogen_conversable_agent, autogen_user_proxy_agent | AutoGen executor with code execution has no explicit auto-reply cap | medium | 0.70 | 28.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | -| 151 | AG2-007 | AutoGen | tool | autogen_tool | AutoGen tool has no description | low | 0.90 | 13.5 | [autogen/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/tool_definition.yaml) | -| 152 | AG2-008 | AutoGen | tool | autogen_tool | AutoGen tool parameters are not type-annotated | medium | 0.85 | 34.0 | [autogen/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/tool_definition.yaml) | -| 153 | AG2-009 | AutoGen | tool | autogen_tool | AutoGen tool body spawns a subprocess | high | 0.85 | 59.5 | [autogen/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/shell_safety.yaml) | -| 154 | AG2-010 | AutoGen | tool | autogen_tool | AutoGen tool body evaluates dynamic code | high | 0.85 | 59.5 | [autogen/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/code_execution.yaml) | -| 155 | AG2-011 | AutoGen | tool | autogen_tool | AutoGen tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [autogen/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/ssrf.yaml) | -| 156 | AG2-012 | AutoGen | tool | autogen_tool | AutoGen tool network call has no timeout | high | 0.85 | 59.5 | [autogen/network.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/network.yaml) | -| 157 | AG2-201 | AutoGen | repo | autogen | AutoGen project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [autogen/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/repo_hygiene.yaml) | -| 158 | VAI-001 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool execute() spawns a subprocess | high | 0.85 | 59.5 | [vercel_ai/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/shell_safety.yaml) | -| 159 | VAI-002 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool execute() evaluates code (eval / new Function) | high | 0.90 | 63.0 | [vercel_ai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/code_execution.yaml) | -| 160 | VAI-003 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool execute() fetches a model-controlled URL | high | 0.75 | 52.5 | [vercel_ai/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/ssrf.yaml) | -| 161 | VAI-004 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool has no description | low | 0.90 | 13.5 | [vercel_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/tool_definition.yaml) | -| 162 | VAI-005 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool accepts untyped input | medium | 0.80 | 32.0 | [vercel_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/tool_definition.yaml) | -| 163 | VAI-006 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent wires a provider shell / computer / file-editing / code-execution tool | high | 0.85 | 59.5 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | -| 164 | VAI-007 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent tool loop has no explicit step bound | low | 0.60 | 9.0 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | -| 165 | VAI-008 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent forces a provider execution tool every step | medium | 0.65 | 26.0 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | -| 166 | VAI-009 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent wires a provider tool that retrieves model-chosen web content | medium | 0.70 | 28.0 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | -| 167 | VAI-011 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool HTTP call has no timeout | high | 0.60 | 42.0 | [vercel_ai/network.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/network.yaml) | -| 168 | VAI-012 | Vercel AI | repo | vercel_ai | Vercel AI project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [vercel_ai/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/repo_hygiene.yaml) | -| 169 | PYD-001 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool has no description | low | 0.90 | 13.5 | [pydantic_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/tool_definition.yaml) | -| 170 | PYD-002 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool parameters are not type-annotated | medium | 0.85 | 34.0 | [pydantic_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/tool_definition.yaml) | -| 171 | PYD-003 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool body spawns a subprocess | high | 0.85 | 59.5 | [pydantic_ai/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/shell_safety.yaml) | -| 172 | PYD-004 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool body evaluates dynamic code | high | 0.85 | 59.5 | [pydantic_ai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/code_execution.yaml) | -| 173 | PYD-005 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [pydantic_ai/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/ssrf.yaml) | -| 174 | PYD-006 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool network call has no timeout | high | 0.85 | 59.5 | [pydantic_ai/network.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/network.yaml) | -| 175 | PYD-007 | Pydantic AI | tool | pydantic_ai_tool | Mutating Pydantic AI tool has no idempotency key | medium | 0.55 | 22.0 | [pydantic_ai/idempotency.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/idempotency.yaml) | -| 176 | PYD-101 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent has no structured output validation | low | 0.70 | 10.5 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | -| 177 | PYD-102 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent wires the code-execution native tool | high | 0.85 | 59.5 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | -| 178 | PYD-103 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent wires a model-driven web-fetching or search native tool | medium | 0.75 | 30.0 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | -| 179 | PYD-105 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent retries with the exhaustive end strategy | low | 0.70 | 10.5 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | -| 180 | PYD-201 | Pydantic AI | repo | pydantic_ai | Pydantic AI project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [pydantic_ai/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/repo_hygiene.yaml) | -| 181 | CSKILL-001 | claude_skill | skill | claude_skill | Skill auto-approves unrestricted shell | high | 0.90 | 63.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 182 | CSKILL-002 | claude_skill | skill | claude_skill | Skill runs shell during load (dynamic-context execution) | high | 0.90 | 63.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 183 | CSKILL-003 | claude_skill | skill | claude_skill | Dynamic-context command performs network egress or reads secrets | critical | 0.85 | 85.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 184 | CSKILL-010 | claude_skill | skill | claude_skill | Bundled skill script performs network egress | high | 0.70 | 49.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 185 | CSKILL-011 | claude_skill | skill | claude_skill | Bundled skill script reads credentials or secrets | critical | 0.80 | 80.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 186 | CSKILL-020 | claude_skill | skill | claude_skill | Skill fetches untrusted external content | medium | 0.70 | 28.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 187 | CSKILL-030 | claude_skill | skill | claude_skill | Bundled skill file contains a hardcoded secret | high | 0.85 | 59.5 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 188 | CSKILL-040 | claude_skill | skill | claude_skill | Skill body contains prompt-injection markers | medium | 0.60 | 24.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 189 | CSKILL-050 | claude_skill | skill | claude_skill | Model-invocable skill grants side-effecting tools | high | 0.80 | 56.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | -| 190 | CSKILL-060 | claude_skill | skill | claude_skill | Skill description claims read-only but grants side-effecting tools | medium | 0.50 | 20.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 116 | MCP-023 | MCP | tool | mcp_tool | PHP MCP tool has no type-annotated parameters | medium | 0.85 | 34.0 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | +| 117 | LC-001 | LangChain | tool | langchain_tool | LangChain tool has no description | low | 0.80 | 12.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | +| 118 | LC-002 | LangChain | tool | langchain_tool | LangChain tool parameters are not type-annotated | medium | 0.85 | 34.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | +| 119 | LC-003 | LangChain | tool | langchain_tool | LangChain tool body spawns a subprocess | high | 0.85 | 59.5 | [langchain/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/shell_safety.yaml) | +| 120 | LC-004 | LangChain | tool | langchain_tool | LangChain tool body evaluates dynamic code | high | 0.85 | 59.5 | [langchain/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/code_execution.yaml) | +| 121 | LC-005 | LangChain | tool | langchain_tool | LangChain tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [langchain/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/ssrf.yaml) | +| 122 | LC-006 | LangChain | tool | langchain_tool | LangChain tool returns its output directly, bypassing the model | medium | 0.80 | 32.0 | [langchain/tool_behavior.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_behavior.yaml) | +| 123 | LC-010 | LangChain | tool | langchain_tool | TypeScript LangChain tool has no description | low | 0.80 | 12.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | +| 124 | LC-011 | LangChain | tool | langchain_tool | TypeScript LangChain tool body spawns a subprocess | high | 0.85 | 59.5 | [langchain/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/shell_safety.yaml) | +| 125 | LC-012 | LangChain | tool | langchain_tool | TypeScript LangChain tool evaluates dynamic code | high | 0.85 | 59.5 | [langchain/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/code_execution.yaml) | +| 126 | LC-013 | LangChain | tool | langchain_tool | TypeScript LangChain tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [langchain/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/ssrf.yaml) | +| 127 | LC-014 | LangChain | tool | langchain_tool | TypeScript LangChain tool returns its output directly, bypassing the model | medium | 0.80 | 32.0 | [langchain/tool_behavior.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_behavior.yaml) | +| 128 | LC-101 | LangChain | agent | langchain_agent, langchain_agent_executor, langchain_state_graph | LangChain agent wires a code-execution or shell built-in tool | high | 0.85 | 59.5 | [langchain/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/agent_safety.yaml) | +| 129 | LC-102 | LangChain | agent | langchain_agent_executor | LangChain AgentExecutor has no explicit max_iterations limit | low | 0.60 | 9.0 | [langchain/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/agent_safety.yaml) | +| 130 | LC-111 | LangChain | agent | langchain_agent_executor | TypeScript LangChain AgentExecutor has no explicit maxIterations limit | low | 0.60 | 9.0 | [langchain/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/agent_safety.yaml) | +| 131 | LC-201 | LangChain | repo | langchain | LangChain project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [langchain/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/repo_hygiene.yaml) | +| 132 | CREW-001 | CrewAI | tool | crewai_tool | CrewAI tool has no description | low | 0.90 | 13.5 | [crewai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/tool_definition.yaml) | +| 133 | CREW-002 | CrewAI | tool | crewai_tool | CrewAI tool parameters are not type-annotated | medium | 0.85 | 34.0 | [crewai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/tool_definition.yaml) | +| 134 | CREW-003 | CrewAI | tool | crewai_tool | CrewAI tool body evaluates dynamic code | high | 0.85 | 59.5 | [crewai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/code_execution.yaml) | +| 135 | CREW-004 | CrewAI | tool | crewai_tool | CrewAI tool body spawns a subprocess | high | 0.85 | 59.5 | [crewai/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/shell_safety.yaml) | +| 136 | CREW-005 | CrewAI | tool | crewai_tool | CrewAI tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [crewai/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/ssrf.yaml) | +| 137 | CREW-006 | CrewAI | tool | crewai_tool | Mutating CrewAI tool has no idempotency key | medium | 0.55 | 22.0 | [crewai/idempotency.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/idempotency.yaml) | +| 138 | CREW-101 | CrewAI | agent | crewai_agent | CrewAI agent enables built-in code execution | high | 0.90 | 63.0 | [crewai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/agent_safety.yaml) | +| 139 | CREW-102 | CrewAI | agent | crewai_agent | CrewAI agent runs code execution in unsafe mode | high | 0.90 | 63.0 | [crewai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/agent_safety.yaml) | +| 140 | CREW-103 | CrewAI | agent | crewai_agent | CrewAI agent wires the code-interpreter built-in tool | high | 0.85 | 59.5 | [crewai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/code_execution.yaml) | +| 141 | CREW-104 | CrewAI | agent | crewai_agent | CrewAI agent allows delegation to peer agents | medium | 0.75 | 30.0 | [crewai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/agent_safety.yaml) | +| 142 | CREW-106 | CrewAI | agent | crewai_agent | CrewAI agent grants an unconstrained FileReadTool | high | 0.70 | 49.0 | [crewai/dangerous_tools.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/dangerous_tools.yaml) | +| 143 | CREW-107 | CrewAI | agent | crewai_agent | CrewAI agent wires a tool that fetches model-chosen URLs | medium | 0.70 | 28.0 | [crewai/dangerous_tools.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/dangerous_tools.yaml) | +| 144 | CREW-108 | CrewAI | tool | crewai_tool | CrewAI tool returns its output as the final answer | medium | 0.60 | 24.0 | [crewai/tool_behavior.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/tool_behavior.yaml) | +| 145 | CREW-109 | CrewAI | agent | crewai_agent | CrewAI agent wires a model-driven file-writing tool | high | 0.75 | 52.5 | [crewai/dangerous_tools.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/dangerous_tools.yaml) | +| 146 | CREW-201 | CrewAI | repo | crewai | CrewAI project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [crewai/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/crewai/repo_hygiene.yaml) | +| 147 | AG2-001 | AutoGen | agent | autogen_conversable_agent, autogen_user_proxy_agent | AutoGen executor runs code on the host without Docker | high | 0.90 | 63.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | +| 148 | AG2-002 | AutoGen | agent | autogen_conversable_agent, autogen_user_proxy_agent | AutoGen executor runs code with no human review (human_input_mode=NEVER) | high | 0.85 | 59.5 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | +| 149 | AG2-004 | AutoGen | agent | autogen_group_chat_manager | AutoGen group chat has no explicit max_round bound | low | 0.60 | 9.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | +| 150 | AG2-005 | AutoGen | agent | autogen_assistant_agent | AutoGen AssistantAgent enables code execution on the LLM agent | medium | 0.70 | 28.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | +| 151 | AG2-006 | AutoGen | agent | autogen_conversable_agent, autogen_user_proxy_agent | AutoGen executor with code execution has no explicit auto-reply cap | medium | 0.70 | 28.0 | [autogen/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/agent_safety.yaml) | +| 152 | AG2-007 | AutoGen | tool | autogen_tool | AutoGen tool has no description | low | 0.90 | 13.5 | [autogen/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/tool_definition.yaml) | +| 153 | AG2-008 | AutoGen | tool | autogen_tool | AutoGen tool parameters are not type-annotated | medium | 0.85 | 34.0 | [autogen/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/tool_definition.yaml) | +| 154 | AG2-009 | AutoGen | tool | autogen_tool | AutoGen tool body spawns a subprocess | high | 0.85 | 59.5 | [autogen/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/shell_safety.yaml) | +| 155 | AG2-010 | AutoGen | tool | autogen_tool | AutoGen tool body evaluates dynamic code | high | 0.85 | 59.5 | [autogen/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/code_execution.yaml) | +| 156 | AG2-011 | AutoGen | tool | autogen_tool | AutoGen tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [autogen/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/ssrf.yaml) | +| 157 | AG2-012 | AutoGen | tool | autogen_tool | AutoGen tool network call has no timeout | high | 0.85 | 59.5 | [autogen/network.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/network.yaml) | +| 158 | AG2-201 | AutoGen | repo | autogen | AutoGen project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [autogen/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/autogen/repo_hygiene.yaml) | +| 159 | VAI-001 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool execute() spawns a subprocess | high | 0.85 | 59.5 | [vercel_ai/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/shell_safety.yaml) | +| 160 | VAI-002 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool execute() evaluates code (eval / new Function) | high | 0.90 | 63.0 | [vercel_ai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/code_execution.yaml) | +| 161 | VAI-003 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool execute() fetches a model-controlled URL | high | 0.75 | 52.5 | [vercel_ai/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/ssrf.yaml) | +| 162 | VAI-004 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool has no description | low | 0.90 | 13.5 | [vercel_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/tool_definition.yaml) | +| 163 | VAI-005 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool accepts untyped input | medium | 0.80 | 32.0 | [vercel_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/tool_definition.yaml) | +| 164 | VAI-006 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent wires a provider shell / computer / file-editing / code-execution tool | high | 0.85 | 59.5 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | +| 165 | VAI-007 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent tool loop has no explicit step bound | low | 0.60 | 9.0 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | +| 166 | VAI-008 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent forces a provider execution tool every step | medium | 0.65 | 26.0 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | +| 167 | VAI-009 | Vercel AI | agent | vercel_ai_agent | Vercel AI agent wires a provider tool that retrieves model-chosen web content | medium | 0.70 | 28.0 | [vercel_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/agent_safety.yaml) | +| 168 | VAI-011 | Vercel AI | tool | vercel_ai_tool | Vercel AI tool HTTP call has no timeout | high | 0.60 | 42.0 | [vercel_ai/network.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/network.yaml) | +| 169 | VAI-012 | Vercel AI | repo | vercel_ai | Vercel AI project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [vercel_ai/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/vercel_ai/repo_hygiene.yaml) | +| 170 | PYD-001 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool has no description | low | 0.90 | 13.5 | [pydantic_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/tool_definition.yaml) | +| 171 | PYD-002 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool parameters are not type-annotated | medium | 0.85 | 34.0 | [pydantic_ai/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/tool_definition.yaml) | +| 172 | PYD-003 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool body spawns a subprocess | high | 0.85 | 59.5 | [pydantic_ai/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/shell_safety.yaml) | +| 173 | PYD-004 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool body evaluates dynamic code | high | 0.85 | 59.5 | [pydantic_ai/code_execution.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/code_execution.yaml) | +| 174 | PYD-005 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool fetches a caller-controlled URL (SSRF) | high | 0.80 | 56.0 | [pydantic_ai/ssrf.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/ssrf.yaml) | +| 175 | PYD-006 | Pydantic AI | tool | pydantic_ai_tool | Pydantic AI tool network call has no timeout | high | 0.85 | 59.5 | [pydantic_ai/network.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/network.yaml) | +| 176 | PYD-007 | Pydantic AI | tool | pydantic_ai_tool | Mutating Pydantic AI tool has no idempotency key | medium | 0.55 | 22.0 | [pydantic_ai/idempotency.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/idempotency.yaml) | +| 177 | PYD-101 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent has no structured output validation | low | 0.70 | 10.5 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | +| 178 | PYD-102 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent wires the code-execution native tool | high | 0.85 | 59.5 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | +| 179 | PYD-103 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent wires a model-driven web-fetching or search native tool | medium | 0.75 | 30.0 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | +| 180 | PYD-105 | Pydantic AI | agent | pydantic_ai_agent | Pydantic AI agent retries with the exhaustive end strategy | low | 0.70 | 10.5 | [pydantic_ai/agent_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/agent_safety.yaml) | +| 181 | PYD-201 | Pydantic AI | repo | pydantic_ai | Pydantic AI project ships no agent-guidance doc (AGENTS.md/CLAUDE.md) | low | 0.90 | 13.5 | [pydantic_ai/repo_hygiene.yaml](https://github.com/trustabl/trustabl-rules/blob/main/pydantic_ai/repo_hygiene.yaml) | +| 182 | CSKILL-001 | claude_skill | skill | claude_skill | Skill auto-approves unrestricted shell | high | 0.90 | 63.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 183 | CSKILL-002 | claude_skill | skill | claude_skill | Skill runs shell during load (dynamic-context execution) | high | 0.90 | 63.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 184 | CSKILL-003 | claude_skill | skill | claude_skill | Dynamic-context command performs network egress or reads secrets | critical | 0.85 | 85.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 185 | CSKILL-010 | claude_skill | skill | claude_skill | Bundled skill script performs network egress | high | 0.70 | 49.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 186 | CSKILL-011 | claude_skill | skill | claude_skill | Bundled skill script reads credentials or secrets | critical | 0.80 | 80.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 187 | CSKILL-020 | claude_skill | skill | claude_skill | Skill fetches untrusted external content | medium | 0.70 | 28.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 188 | CSKILL-030 | claude_skill | skill | claude_skill | Bundled skill file contains a hardcoded secret | high | 0.85 | 59.5 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 189 | CSKILL-040 | claude_skill | skill | claude_skill | Skill body contains prompt-injection markers | medium | 0.60 | 24.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 190 | CSKILL-050 | claude_skill | skill | claude_skill | Model-invocable skill grants side-effecting tools | high | 0.80 | 56.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | +| 191 | CSKILL-060 | claude_skill | skill | claude_skill | Skill description claims read-only but grants side-effecting tools | medium | 0.50 | 20.0 | [claude_skill/skill_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/claude_skill/skill_safety.yaml) | diff --git a/docs/Policy/mcp/tool_definition.md b/docs/Policy/mcp/tool_definition.md index 935db29..9a5e9de 100644 --- a/docs/Policy/mcp/tool_definition.md +++ b/docs/Policy/mcp/tool_definition.md @@ -63,6 +63,11 @@ rules: confidence: 0.85 scope: tool fix_type: code + - id: MCP-023 + severity: medium + confidence: 0.85 + scope: tool + fix_type: code references: [LLM06] --- @@ -70,7 +75,7 @@ references: [LLM06] **Policy ID:** `mcp_tool_definition` **File:** `mcp/tool_definition.yaml` -**Rules:** MCP-001, MCP-002, MCP-003, MCP-011, MCP-015, MCP-016, MCP-017, MCP-018, MCP-019, MCP-020, MCP-021, MCP-022 +**Rules:** MCP-001, MCP-002, MCP-003, MCP-011, MCP-015, MCP-016, MCP-017, MCP-018, MCP-019, MCP-020, MCP-021, MCP-022, MCP-023 **References:** LLM06 (Excessive Agency) > Shares the structural-hygiene threat model with @@ -91,9 +96,9 @@ predicate `mcp_tool` kind) and the TypeScript `@modelcontextprotocol/sdk` community php-mcp/server) `#[McpTool]`-attributed methods. MCP-001/002/003 are the Python rules; MCP-011 is the TypeScript description rule; MCP-015/016 are the Go rules; MCP-017 (no description) and MCP-018 (ambiguous name) are the C# rules; -MCP-019 (no description) and MCP-020 (ambiguous name) are the PHP rules; MCP-021 -(no description) and MCP-022 (ambiguous name) are the Rust rules (official rmcp -crate, `#[tool]`-attributed methods). +MCP-019 (no description), MCP-020 (ambiguous name), and MCP-023 (untyped +parameters) are the PHP rules; MCP-021 (no description) and MCP-022 (ambiguous +name) are the Rust rules (official rmcp crate, `#[tool]`-attributed methods). ## Why definition hygiene is sharper for MCP than for an in-process SDK @@ -249,6 +254,39 @@ ambiguous name gives the model no intent signal and collides across servers in a shared session, and the cost is paid by every uncontrolled consumer of the published catalog. +### MCP-023 — PHP MCP tool has no type-annotated parameters (Severity: medium, Confidence: 0.85, Fix type: code) + +**What we detect:** a `#[McpTool]`-attributed PHP method that has parameters but +no type hints (`has_params: true` and `has_typed_params: false`). Discovery sets +`HasTypedParams` when any `simple_parameter` carries a type field; PHP type +hints are optional, so an untyped `function search($query, $limit)` is a real +signal, unlike Go / C# / Rust where the analogous rule would never fire. + +**Why it is flaggable:** MCP derives the published input JSON schema from those +type hints. Without them the advertised schema is unconstrained, so connecting +models send inputs the handler cannot rely on and runtime errors surface inside +the server — the same mechanism as +[MCP-002](#mcp-002--tool-has-no-type-annotated-parameters-severity-medium-confidence-085-fix-type-code) +on Python. Medium severity: degraded validation is a reliability and minor +injection-surface concern (LLM06: the model can pass anything), not a direct +compromise. Confidence 0.85 matches MCP-002: a tool that validates by hand +inside the body, or that publishes a schema some other way, still fires because +the predicate cannot see that. + +**Real-world consequence:** `#[McpTool(name: 'refund')] public function refund($id, $cents)` +advertises two unconstrained arguments. A connected model (or a prompt-injected +client) sends `$cents = "all"` or an array; the handler fatals or refunds the +wrong amount, and the opaque PHP error crosses the MCP trust boundary. + +**Why severity is medium and not high:** missing types degrade the contract; they +do not by themselves grant shell or network. Not low: every consumer of the +server inherits the unconstrained schema. **Fix type — code:** adding `string +$id, int $cents` is a source edit. **Confidence 0.85:** residual false positives +are a handler that constrains inputs without hints (runtime `is_int` checks, a +separately-published schema) and mixed-hint signatures where *any* typed +parameter makes discovery report `HasTypedParams=true` (so a `$query` plus +`int $limit` is silent). + --- ## What this policy does not cover @@ -267,10 +305,10 @@ untyped-params likewise has no analog (C# is statically typed), the plus the Semantic Kernel `[KernelFunction]` / AutoGen `[Function]` shapes await later work. For PHP, the multi-line `#[...]` attribute form is not read (the grammar parses single-line attributes as comments), `#[McpResource]` / -`#[McpPrompt]` are not discovered, and body-fact rules await PHP AST predicates; -unlike Go and C#, PHP type hints are optional, so an untyped-params analog of -MCP-002 *is* meaningful — discovery already captures `HasTypedParams`, and that -rule is a deliberate fast-follow rather than not applicable. For Rust, +`#[McpPrompt]` are not discovered, and body-fact rules await PHP AST predicates. +MCP-023 now covers the untyped-params analog of MCP-002; it still cannot see +mixed-hint signatures (one typed parameter silences the rule) or a schema +published outside the method signature. For Rust, untyped-params has no analog (Rust is statically typed, and the input schema lives in a separate `#[derive(JsonSchema)]` struct passed via `Parameters`, which is not yet resolved); raw-string descriptions, `#[tool]` on free functions outside an diff --git a/mcp/POLICY_INDEX.md b/mcp/POLICY_INDEX.md index e9cd23a..285788d 100644 --- a/mcp/POLICY_INDEX.md +++ b/mcp/POLICY_INDEX.md @@ -1,7 +1,7 @@ # Model Context Protocol policy index -22 rules — 22 tool +23 rules — 23 tool Risk score = `severity_weight × confidence × 100` (engine formula; weights: low=0.15, medium=0.40, high=0.70). Higher = worse. @@ -29,3 +29,4 @@ Risk score = `severity_weight × confidence × 100` (engine formula; weights: lo | 20 | MCP-020 | MCP | tool | mcp_tool | Ambiguous PHP MCP tool name | low | 0.85 | 12.8 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 21 | MCP-021 | MCP | tool | mcp_tool | Rust MCP tool has no description | low | 0.85 | 12.8 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 22 | MCP-022 | MCP | tool | mcp_tool | Ambiguous Rust MCP tool name | low | 0.85 | 12.8 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | +| 23 | MCP-023 | MCP | tool | mcp_tool | PHP MCP tool has no type-annotated parameters | medium | 0.85 | 34.0 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | From 8cbd8c0202b4a7be01f9e447edadebbcd0452fb0 Mon Sep 17 00:00:00 2001 From: Phoenix Wang Date: Mon, 24 Aug 2026 15:03:37 -0400 Subject: [PATCH 2/2] docs(mcp): renumber rationale to MCP-029 to avoid an ID collision Mirrors the rules-repo renumber across the rationale doc front-matter, the rule-by-rule defense heading, and both policy indexes. Co-authored-by: Cursor --- POLICY_INDEX.md | 2 +- docs/Policy/mcp/tool_definition.md | 10 +++++----- mcp/POLICY_INDEX.md | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/POLICY_INDEX.md b/POLICY_INDEX.md index 3a600c5..52e01f6 100644 --- a/POLICY_INDEX.md +++ b/POLICY_INDEX.md @@ -170,7 +170,7 @@ Users can contribute their own policies by: | 113 | MCP-020 | MCP | tool | mcp_tool | Ambiguous PHP MCP tool name | low | 0.85 | 12.8 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 114 | MCP-021 | MCP | tool | mcp_tool | Rust MCP tool has no description | low | 0.85 | 12.8 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 115 | MCP-022 | MCP | tool | mcp_tool | Ambiguous Rust MCP tool name | low | 0.85 | 12.8 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | -| 116 | MCP-023 | MCP | tool | mcp_tool | PHP MCP tool has no type-annotated parameters | medium | 0.85 | 34.0 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | +| 116 | MCP-029 | MCP | tool | mcp_tool | PHP MCP tool has no type-annotated parameters | medium | 0.85 | 34.0 | [mcp/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 117 | LC-001 | LangChain | tool | langchain_tool | LangChain tool has no description | low | 0.80 | 12.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | | 118 | LC-002 | LangChain | tool | langchain_tool | LangChain tool parameters are not type-annotated | medium | 0.85 | 34.0 | [langchain/tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/tool_definition.yaml) | | 119 | LC-003 | LangChain | tool | langchain_tool | LangChain tool body spawns a subprocess | high | 0.85 | 59.5 | [langchain/shell_safety.yaml](https://github.com/trustabl/trustabl-rules/blob/main/langchain/shell_safety.yaml) | diff --git a/docs/Policy/mcp/tool_definition.md b/docs/Policy/mcp/tool_definition.md index 9a5e9de..3a5d940 100644 --- a/docs/Policy/mcp/tool_definition.md +++ b/docs/Policy/mcp/tool_definition.md @@ -63,7 +63,7 @@ rules: confidence: 0.85 scope: tool fix_type: code - - id: MCP-023 + - id: MCP-029 severity: medium confidence: 0.85 scope: tool @@ -75,7 +75,7 @@ references: [LLM06] **Policy ID:** `mcp_tool_definition` **File:** `mcp/tool_definition.yaml` -**Rules:** MCP-001, MCP-002, MCP-003, MCP-011, MCP-015, MCP-016, MCP-017, MCP-018, MCP-019, MCP-020, MCP-021, MCP-022, MCP-023 +**Rules:** MCP-001, MCP-002, MCP-003, MCP-011, MCP-015, MCP-016, MCP-017, MCP-018, MCP-019, MCP-020, MCP-021, MCP-022, MCP-029 **References:** LLM06 (Excessive Agency) > Shares the structural-hygiene threat model with @@ -96,7 +96,7 @@ predicate `mcp_tool` kind) and the TypeScript `@modelcontextprotocol/sdk` community php-mcp/server) `#[McpTool]`-attributed methods. MCP-001/002/003 are the Python rules; MCP-011 is the TypeScript description rule; MCP-015/016 are the Go rules; MCP-017 (no description) and MCP-018 (ambiguous name) are the C# rules; -MCP-019 (no description), MCP-020 (ambiguous name), and MCP-023 (untyped +MCP-019 (no description), MCP-020 (ambiguous name), and MCP-029 (untyped parameters) are the PHP rules; MCP-021 (no description) and MCP-022 (ambiguous name) are the Rust rules (official rmcp crate, `#[tool]`-attributed methods). @@ -254,7 +254,7 @@ ambiguous name gives the model no intent signal and collides across servers in a shared session, and the cost is paid by every uncontrolled consumer of the published catalog. -### MCP-023 — PHP MCP tool has no type-annotated parameters (Severity: medium, Confidence: 0.85, Fix type: code) +### MCP-029 — PHP MCP tool has no type-annotated parameters (Severity: medium, Confidence: 0.85, Fix type: code) **What we detect:** a `#[McpTool]`-attributed PHP method that has parameters but no type hints (`has_params: true` and `has_typed_params: false`). Discovery sets @@ -306,7 +306,7 @@ plus the Semantic Kernel `[KernelFunction]` / AutoGen `[Function]` shapes await later work. For PHP, the multi-line `#[...]` attribute form is not read (the grammar parses single-line attributes as comments), `#[McpResource]` / `#[McpPrompt]` are not discovered, and body-fact rules await PHP AST predicates. -MCP-023 now covers the untyped-params analog of MCP-002; it still cannot see +MCP-029 now covers the untyped-params analog of MCP-002; it still cannot see mixed-hint signatures (one typed parameter silences the rule) or a schema published outside the method signature. For Rust, untyped-params has no analog (Rust is statically typed, and the input schema lives diff --git a/mcp/POLICY_INDEX.md b/mcp/POLICY_INDEX.md index 285788d..a8d6bb9 100644 --- a/mcp/POLICY_INDEX.md +++ b/mcp/POLICY_INDEX.md @@ -29,4 +29,4 @@ Risk score = `severity_weight × confidence × 100` (engine formula; weights: lo | 20 | MCP-020 | MCP | tool | mcp_tool | Ambiguous PHP MCP tool name | low | 0.85 | 12.8 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 21 | MCP-021 | MCP | tool | mcp_tool | Rust MCP tool has no description | low | 0.85 | 12.8 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | | 22 | MCP-022 | MCP | tool | mcp_tool | Ambiguous Rust MCP tool name | low | 0.85 | 12.8 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | -| 23 | MCP-023 | MCP | tool | mcp_tool | PHP MCP tool has no type-annotated parameters | medium | 0.85 | 34.0 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) | +| 23 | MCP-029 | MCP | tool | mcp_tool | PHP MCP tool has no type-annotated parameters | medium | 0.85 | 34.0 | [tool_definition.yaml](https://github.com/trustabl/trustabl-rules/blob/main/mcp/tool_definition.yaml) |