T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/start_chrome.py:29
- Finding
- Environment-Controlled Shell Command Injection in Chrome Launcher## Vulnerability Details **File Location**: `scripts/start_chrome.py`, lines 29-39 and 67-79 **Vulnerability Type**: OS command injection through environment-controlled command construction **Risk Level**: High ### Vulnerable Code ```python CHROME_EXE = os.getenv( "CHROME_EXE", r"C:\Program Files\Google\Chrome\Application\chrome.exe" ) SRC_DIR = os.path.expandvars( os.getenv("CHROME_SRC_DIR", r"%LOCALAPPDATA%\Google\Chrome\User Data") ) DST_DIR = os.getenv( "CHROME_PROFILE_DIR", os.path.join(os.path.expandvars("%TEMP%"), "browser-use-chrome-profile") ) ``` ```python def start_chrome(): cmd = ( f'"{CHROME_EXE}"' f' --remote-debugging-port={PORT}' f' --remote-allow-origins=*' f' --user-data-dir="{DST_DIR}"' f' --profile-directory=Default' f' --no-first-run' f' --no-default-browser-check' ) subprocess.Popen(cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) ``` ### Technical Analysis `CHROME_EXE` and `DST_DIR` are populated from the `CHROME_EXE` and `CHROME_PROFILE_DIR` environment variables. These values are directly interpolated into a command string that is executed with `shell=True`. Quoting the values does not make this safe. A malicious value containing a quote followed by Windows command-shell metacharacters can terminate the intended argument and append another command. Because the resulting string is interpreted by the shell rather than passed directly to Chrome as an argument array, attacker-controlled environment data can alter the command structure. This vulnerability is reachable whenever an attacker can influence the process environment, such as through a wrapper script, compromised launcher, shared automation configuration, CI environment, or poisoned shell profile. ### Attack Path 1. An attacker gains the ability to set or influence `CHROME_EXE` or `CHROME_PROFILE ...[truncated 896 chars]
- Remediation
- ## Remediation Suggestions - Remove `shell=True` and invoke Chrome using an argument list so values are never interpreted as command syntax: ```python cmd = [ CHROME_EXE, f"--remote-debugging-port={PORT}", "--user-data-dir=" + DST_DIR, "--profile-directory=Default", "--no-first-run", "--no-default-browser-check", ] subprocess.Popen( cmd, shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) ``` - Resolve the executable to an absolute path and verify that it exists and is a regular executable file. - Reject unexpected control characters and validate that the profile directory resolves to an approved user-owned location. - Validate `CDP_PORT` to ensure it is within the valid TCP port range. - Do not attempt to secure shell command construction through manual escaping alone; avoiding the shell is the appropriate control.
