{"record":{"id":"4ba851b8b6ddfc30","repo":"unicity-aos/aos-ce","slug":"rejected-invalid-tool-name-tool-name","errorCode":null,"errorMessage":"Rejected invalid tool name: {tool_name}","messagePattern":"Rejected invalid tool name: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"capsules/capsule-router/src/lib.rs","lineNumber":44,"sourceCode":"    #[astrid::interceptor(\"handle_execute_request\")]\n    pub fn handle_execute_request(&self, req: IpcPayload) -> Result<(), SysError> {\n        let (call_id, tool_name, arguments) = match req {\n            IpcPayload::ToolExecuteRequest {\n                call_id,\n                tool_name,\n                arguments,\n            } => (call_id, tool_name, arguments),\n            _ => return Ok(()),\n        };\n\n        // Validate tool name: must be non-empty, alphanumeric with hyphens/underscores/colons.\n        // Reject dots to prevent topic injection (e.g., \"foo.bar.baz\" becoming nested topics).\n        if tool_name.is_empty()\n            || tool_name\n                .chars()\n                .any(|c| !c.is_alphanumeric() && c != '-' && c != '_' && c != ':')\n        {\n            log::warn(format!(\"Rejected invalid tool name: {tool_name}\"));\n            return Self::publish_error_result(&call_id, format!(\"Invalid tool name: {tool_name}\"));\n        }\n\n        let forward_topic = format!(\"tool.v1.execute.{tool_name}\");\n\n        log::info(format!(\n            \"Routing tool request: {tool_name} -> {forward_topic}\"\n        ));\n\n        let forward_payload = IpcPayload::ToolExecuteRequest {\n            call_id: call_id.clone(),\n            tool_name: tool_name.clone(),\n            arguments,\n        };\n\n        if let Err(e) = ipc::publish_json(&forward_topic, &forward_payload) {\n            log::error(format!(\n                \"Failed to forward tool request for {tool_name}: {e}\"","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/capsules/capsule-router/src/lib.rs#L26-L62","documentation":"The router validates tool names before constructing the forward topic tool.v1.execute.{tool_name}. A name that is empty or contains characters outside [alphanumeric, '-', '_', ':'] is rejected to prevent topic injection (e.g., dots creating nested topics). The warning is logged and an error result is published back to the caller with the call_id.","triggerScenarios":"handle_execute_request receives a tool_call whose name is empty, contains a dot, slash, space, or any non-allowlisted character — e.g., tool_name = \"foo.bar.baz\", \"../exec\", \"my tool\", or \"\".","commonSituations":"Clients building tool names from user input or file paths; LLM-generated tool calls with dotted names; namespace conventions using '.' from other ecosystems; empty names from defaulted/misbuilt JSON-RPC calls.","solutions":["Sanitize the tool name on the caller side to allow only [A-Za-z0-9_-:], replacing dots with ':' or '-'.","Reject or map dotted names to the router's convention before calling execute.","Ensure empty tool names never reach the router (validate JSON-RPC params).","If a legitimate name needs new characters, extend the allowlist in the router deliberately."],"exampleFix":"// before\ncall_tool(\"foo.bar.baz\", args) // dot rejected\n// after\ncall_tool(\"foo:bar:baz\", args) // ':' is allowed by the router","handlingStrategy":"validation","validationCode":"function isValidToolName(name) {\n  return typeof name === 'string' && name.length > 0 &&\n    /^[A-Za-z0-9_:-]+$/.test(name);\n}","typeGuard":"fn is_safe_tool_name(name: &str) -> bool {\n    !name.is_empty()\n        && name.chars().all(|c| c.is_alphanumeric() || matches!(c, '-' | '_' | ':'))\n}","tryCatchPattern":"if (!isValidToolName(toolName)) {\n  console.warn('Rejected invalid tool name:', toolName);\n  return publishError(callId, 'Invalid tool name: ' + toolName);\n}","preventionTips":["Never build tool names from raw user input or file paths","Replace dots with ':' before calling execute","Validate JSON-RPC params so empty names are caught client-side"],"tags":["validation","tool-name","topic-injection","security"],"backgroundTag":"invalid-identifier-format","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}