T09 · Insecure Skill Coding Practices
Error
- Location
- dashboard.js:174
- Finding
- OS Command Injection via ECONOMIC_TRACKER_PATH<![CDATA[ ## Vulnerability Details **File Location**: `dashboard.js:35-36`, `dashboard.js:174-176` **Vulnerability Type**: OS command injection through an untrusted environment variable **Risk Level**: High The tracker path is read directly from the process environment: ```js economicTracker: { enabled: process.env.ECONOMIC_TRACKER_PATH ? true : false, path: process.env.ECONOMIC_TRACKER_PATH || '' }, ``` It is subsequently interpolated into a command string executed through a system shell: ```js const { execSync } = require('child_process'); const output = execSync(`python3 ${CONFIG.economicTracker.path} status`, { timeout: 5000, encoding: 'utf8' }); ``` ### Technical Analysis `ECONOMIC_TRACKER_PATH` is not validated, escaped, or constrained to an approved filesystem location. `child_process.execSync()` executes its string argument through a shell. Consequently, shell metacharacters embedded in the environment variable are interpreted as command syntax rather than as part of a file path. This permits command injection whenever an attacker can set or influence the dashboard process's environment. Merely quoting the value would not be a sufficient long-term fix because shell quoting is error-prone and platform-dependent. The operation does not require a shell at all. ### Attack Path 1. An attacker obtains the ability to define or modify `ECONOMIC_TRACKER_PATH`. Potential sources include a compromised launcher, cron configuration, service environment file, CI job, wrapper script, or another process configuration mechanism. 2. The attacker sets the variable to a value containing shell syntax, such as: ```text /tmp/tracker.py; id; # ``` 3. The dashboard is launched normally with `node dashboard.js`. 4. `getEconomicStatus()` constructs the following effective shell command: ```sh python3 /tmp/tracker.py; id; # status ``` 5. The shell runs the injected `id` command in addition to attempting to run the configured tracker. 6. The at ...[truncated 1140 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Avoid invoking a shell. Pass the executable and arguments separately with `execFileSync()`: ```js const { execFileSync } = require('child_process'); const path = require('path'); const fs = require('fs'); const trackerPath = path.resolve(CONFIG.economicTracker.path); const allowedDirectory = path.resolve('/opt/crypto-dashboard/trackers'); if ( trackerPath !== allowedDirectory && !trackerPath.startsWith(`${allowedDirectory}${path.sep}`) ) { throw new Error('Economic tracker path is outside the approved directory'); } const stat = fs.statSync(trackerPath); if (!stat.isFile()) { throw new Error('Economic tracker path must identify a regular file'); } const output = execFileSync('python3', [trackerPath, 'status'], { timeout: 5000, encoding: 'utf8', shell: false, windowsHide: true }); ``` Additional hardening measures: 1. Resolve the configured path to an absolute, canonical path before use. 2. Restrict tracker scripts to a dedicated administrator-controlled directory. 3. Reject symlinks if untrusted users can modify the tracker directory. 4. Verify that the tracker is a regular file with safe ownership and permissions. 5. Run the dashboard under a dedicated, unprivileged operating-system account. 6. Supply only the environment variables required by the tracker rather than automatically inheriting sensitive credentials. 7. Do not permit untrusted users to edit cron entries, service environment files, or launcher configuration. 8. Log tracker validation failures without printing credentials or other sensitive environment data. ]]>
