T09 · Insecure Skill Coding Practices
Error
- Location
- index.js:326
- Finding
- Shell Command Injection Through Configurable Output Directory## Vulnerability Details **File Location**: `index.js:39-47`, `index.js:278-287`, and `index.js:326-345` **Vulnerability Type**: OS command injection through shell-based process execution **Risk Level**: High ### Vulnerable Code ```javascript const config = { appKey: process.env.DINGTALK_APP_KEY || fileConfig.appKey, appSecret: process.env.DINGTALK_APP_SECRET || fileConfig.appSecret, agentId: process.env.DINGTALK_AGENT_ID || fileConfig.agentId, appId: process.env.DINGTALK_APP_ID || fileConfig.appId, outputDir: process.env.OUTPUT_DIR || fileConfig.outputDir || './data/attendance', outputFormat: process.env.OUTPUT_FORMAT || fileConfig.outputFormat || 'json', notifyChannel: process.env.NOTIFY_CHANNEL || fileConfig.notifyChannel || 'webchat', userFetchConcurrency: process.env.USER_FETCH_CONCURRENCY || fileConfig.userFetchConcurrency || 4, attendanceFetchConcurrency: process.env.ATTENDANCE_FETCH_CONCURRENCY || fileConfig.attendanceFetchConcurrency || 8 }; ``` ```javascript function exportData(data, filename) { const outputDir = path.resolve(__dirname, config.outputDir || './data/attendance'); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } const filepath = path.join(outputDir, filename); fs.writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf-8'); console.log(`📁 Data saved to: ${filepath}`); return filepath; } ``` ```javascript function exportToExcel(jsonFile) { return new Promise((resolve, reject) => { const pythonScript = path.join(__dirname, 'export_excel.py'); const pythonCmd = jsonFile ? `python "${pythonScript}" "${jsonFile}"` : `python "${pythonScript}"`; console.log(' Executing: ', pythonCmd); exec(pythonCmd, { cwd: __dirname }, (error, stdout, stderr) => { if (error) { console.error(' Excel export failed:', error.message); reject(error); ...[truncated 2726 chars]
- Remediation
- ## Remediation Suggestions Replace shell-string execution with an argument-based API that does not invoke a shell: ```javascript const { execFile } = require('child_process'); execFile( 'python', [pythonScript, jsonFile], { cwd: __dirname, shell: false }, callback ); ``` Additional hardening should include: 1. Resolve `OUTPUT_DIR` against a fixed, administrator-approved base directory. 2. Reject paths that escape the approved directory after canonicalization. 3. Do not accept arbitrary output paths from untrusted environment or configuration sources. 4. Avoid logging full commands or sensitive paths unnecessarily. 5. Run the Skill under a dedicated, unprivileged operating-system account. 6. Add tests using paths containing quotes, spaces, semicolons, command substitutions, and platform-specific shell metacharacters.
