T09 · Insecure Skill Coding Practices
- Location
scripts/browser_dom.py:85- Finding
Agent Tool-Call Injection Through an Unescaped Page URL
- Content
View full analysis
Vulnerability Details
File Location:
scripts/browser_dom.py:85-108
Vulnerability Type: Agent instruction injection caused by unsafe string interpolation
Risk Level: HighVulnerable Code
python def generate_instruction(self, modal_id: str, page_url: Optional[str] = None, output_path: Optional[str] = None) -> Dict: """Generate browser operation instructions.""" if not page_url: page_url = f"https://www.douyin.com/video/{modal_id}" if not output_path: output_path = f"/path/to/temp/douyin\\douyin_{modal_id}.mp4" return { "needs_agent": True, "modal_id": modal_id, "page_url": page_url, "output_path": output_path, "steps": [ { "step": 1, "description": "Open the Douyin video page", "tool_call": f"browser(action='open', profile='openclaw', targetUrl='{page_url}')" },The original source contains Chinese descriptions, but the executable statement is reproduced without alteration.
Technical Analysis
page_urlis inserted directly into a single-quoted, executable-looking browser tool call. The value is neither escaped nor represented as a structured argument object. A page URL containing a quote can terminate thetargetUrlvalue and append attacker-controlled tool-call syntax.The vulnerable method can receive a URL propagated by
scripts/fetcher.py, andbrowser_dom.pyalso acceptspage_urldirectly from a command-line argument. The generated instruction is explicitly intended for an OpenClaw Agent to execute. Consequently, the boundary between untrusted data and Agent instructions is not preserved.This is distinct from ordinary URL redirection: the attacker can alter the textual structure of the generated tool instruction itself.
Attack Path
- An attacker supplies a crafted
page_urlcon ...[truncated 1010 chars]
- An attacker supplies a crafted
- Remediation
View remediation
Remediation Suggestions
-
Do not serialize tool calls as executable strings. Return structured data, for example:
python { "tool": "browser", "arguments": { "action": "open", "profile": "openclaw", "targetUrl": validated_url } } -
Parse URLs with
urllib.parse.urlsplit. -
Require the
httpsscheme. -
Reject embedded credentials, control characters, quotes, unexpected ports, and malformed URLs.
-
Permit only an explicit hostname allowlist such as
www.douyin.comandv.douyin.com, including only required subdomains. -
Ensure the Agent treats every returned field as data rather than instructions that can introduce additional tool calls.
-
Add tests using quote characters, newlines, backslashes, and tool-call-like payloads.
-
