T09 · Insecure Skill Coding Practices
- Location
run_browser.js:26- Finding
Arbitrary Command Execution Through Shell Injection in the URL Argument
- Content
View full analysis
Vulnerability Details
File Location:
run_browser.js:26-28
Vulnerability Type: OS command injection
Risk Level: HighVulnerable Code
javascript const command = `agent-browser --url="${url}" --output=markdown --timeout=10000`; exec(command, { timeout: 15000 }, (error, stdout, stderr) => {Technical Analysis
The URL is obtained directly from
process.argv[2]and interpolated into a command string passed tochild_process.exec. Theexecfunction launches a shell, so shell metacharacters and command substitutions in the URL are interpreted by that shell.Placing the value inside double quotes does not make it safe. For example, command substitution syntax such as
$(command)remains active inside double-quoted shell strings. An attacker can also inject a closing quote followed by shell operators.There is no URL scheme validation, shell escaping, or argument separation before execution.
Attack Path
- An attacker supplies a crafted value where the skill expects a URL.
- OpenClaw invokes
run_browser.jswith that value as its first argument. - The script inserts the value into the
commandtemplate literal. execpasses the resulting string to a system shell.- The shell evaluates the injected command substitution or operators before or while invoking
agent-browser. - The injected command executes with the identity and environment of the OpenClaw or Node.js process.
A value containing shell substitution, conceptually
https://example.invalid/$(attacker-command), is sufficient to reach shell evaluation despite the surrounding double quotes.Impact Assessment
Successful exploitation provides arbitrary command execution under the operating-system account running the skill. An attacker could read or alter files accessible to that account, access environment variables and local credentials, execute other installed programs, make network requests, or modify the ...[truncated 300 chars]
- Remediation
View remediation
Remediation Suggestions
Replace shell-based execution with
execFileorspawn, pass every option as a distinct argument, and explicitly disable shell processing:javascript const { execFile } = require('child_process'); let parsedUrl; try { parsedUrl = new URL(url); } catch { console.error('Invalid URL'); process.exit(1); } if (!['http:', 'https:'].includes(parsedUrl.protocol)) { console.error('Only HTTP and HTTPS URLs are permitted'); process.exit(1); } execFile( 'agent-browser', [ `--url=${parsedUrl.href}`, '--output=markdown', '--timeout=10000' ], { timeout: 15000, shell: false }, callback );In addition:
- Reject non-HTTP and non-HTTPS schemes.
- Consider restricting destination hosts if arbitrary browsing is unnecessary.
- Apply network controls to block loopback, link-local, private-network, and cloud metadata destinations where appropriate.
- Run the browser process under a minimally privileged account.
- Do not attempt to solve this solely through manual shell escaping; avoiding a shell is the safer design.
