T09 · Insecure Skill Coding Practices
- Location
api/browser/open-url.js:38- Finding
Shell Command Injection Through Untrusted Clinic URLs
- Content
View full analysis
hostname === host || hostname.endsWith('.' + host)) } catch { return false } } ``` ### Technical Analysis The function verifies that the parsed hostname belongs to `i.beautsgo.com`, but it subsequently interpolates the original, unnormalized URL into a shell command executed through `child_process.exec()`. Hostname validation does not make a string safe for shell interpolation. A URL can have an allowed hostname while containing quotes and shell metacharacters in its path, query, or fragment. These characters may terminate the quoted URL argument and introduce an additional shell command. Clinic URLs can come from the remotely refreshed hospital list. The resolution logic can also use `context.resolvedHospital.url` when the clinic name cannot be matched locally. Consequently, the URL cannot safely be treated as a trusted command-line literal. ### Attack Path 1. An attacker causes a clinic record or supplied context to contain a URL whose parsed hostname remains `i.beautsgo.com`. 2. The URL includes shell syntax outside an injected quotation mark, such as an additional command in its path or query. 3. The user invokes an operation that opens ...[truncated 790 chars]- Remediation
View remediation
{ const child = spawn(command, args, { shell: false, detached: false, stdio: 'ignore', }) child.once('error', reject) child.once('exit', code => { if (code === 0) resolve() else reject(new Error(`Browser launcher exited with code ${code}`)) }) }) } async function openUrl(input) { const parsed = new URL(input) if ( parsed.protocol !== 'https:' || parsed.hostname !== 'i.beautsgo.com' || parsed.username || parsed.password ) { throw new Error('URL not allowed') } const safeUrl = parsed.href if (process.platform === 'darwin') { return launch('open', [safeUrl]) } if (process.platform === 'win32') { return launch('cmd.exe', ['/d', '/s', '/c', 'start', '', safeUrl]) } return launch('xdg-open', [safeUrl]) } ``` On Windows, prefer a native URL-opening API that does not require `cmd.exe`; if `cmd.exe` is unavoidable, apply Windows-specific argument handling and strict URL validation. ]]>
