T09 · Insecure Skill Coding Practices
- Location
scripts/send-report.js:96- Finding
Shell Command Injection Through an Unquoted Scanner Path
- Content
View full analysis
Vulnerability Details
File Location:
scripts/send-report.js, lines 96–100
Vulnerability Type: Shell command injection caused by constructing a command string from an unquoted filesystem path
Risk Level: Mediumjs execSync(`node ${join(__dirname, 'scanner.js')}`, { stdio: 'inherit', cwd: __dirname, timeout: 120000, // 2-minute timeout });Technical Analysis
execSync()receives a command string and executes it through a system shell. The absolute path produced byjoin(__dirname, 'scanner.js')is interpolated directly into that string without shell-safe quoting.Although the filename
scanner.jsis fixed,__dirnamedepends on the directory in which the Skill is installed. If an attacker can influence that installation path and include shell metacharacters in a directory name, the shell may interpret part of the path as additional syntax rather than as a literal scanner path.This issue does not provide a remote exploitation path by itself. Exploitation requires the attacker to control or materially influence the directory into which the Skill is copied, extracted, or installed.
Attack Path
- An attacker causes the Skill to be installed or extracted under a directory name containing shell metacharacters and an attacker-selected command.
- The user, automation, or documented scheduled task starts
send-report.js. - Line 96 constructs a shell command by concatenating
nodewith the attacker-influenced absolute path. execSync()passes the resulting string to the system shell.- The shell interprets the metacharacters and executes the injected command with the privileges of the account running the report.
Impact Assessment
Successful exploitation permits arbitrary local command execution under the operating-system account that invokes
send-report.js. The attacker could access or modify files available to that account, execute programs, read local configurat ...[truncated 235 chars]- Remediation
View remediation
Remediation Suggestions
Avoid passing a constructed command string to a shell. Invoke the Node.js executable directly with a separate argument array:
js import { execFileSync } from 'child_process'; execFileSync(process.execPath, [join(__dirname, 'scanner.js')], { stdio: 'inherit', cwd: __dirname, timeout: 120000, });execFileSync()does not use a shell by default, so metacharacters in the installation path are treated as literal path characters. Usingprocess.execPathalso ensures that the scanner runs with the same Node.js executable as the parent process.As defense in depth:
- Install the Skill only into trusted, administrator-controlled directories.
- Do not attempt to fix the issue solely through manual quoting, because shell escaping differs across operating systems and shells.
- Run scheduled scans under a dedicated, least-privileged account.
- Restrict write access to the Skill directory so untrusted users cannot replace
scanner.jsor alter runtime configuration.
