T09 · Insecure Skill Coding Practices
- Location
src/request_publish.js:25- Finding
Shell Command Injection Through Untrusted CLI Arguments and Stored Post Data
- Content
View full analysis
0) { try { for (const img of images) { const uploadCmd = `node skills/feishu-sender/upload_image.js "${img}"`; const rawOutput = execSync(uploadCmd).toString(); ``` ```js // src/request_publish.js:68-70 const sendCmd = `node skills/feishu-sender/send_post.js "${TARGET_CHAT_ID}" '${msg}'`; try { execSync(sendCmd); ``` ```js // src/approve_post.js:31-37 const msg = JSON.stringify({ zh_cn: { title: "发布成功!🚦", content: [[{ tag: "text", text: `已执行审核通过的操作:${post.content}` }]] } }); require('child_process').execSync( `node skills/feishu-sender/send_post.js "${TARGET_CHAT_ID}" '${msg}'` ); ``` ```js // src/login.js:80-84 // Use send_post logic directly or via exec // Since we are inside node, we can just call the script or reuse logic if modular // But for now, exec is safest to avoid context issues const sendCmd = `node skills/feishu-sender/send_post.js "${TARGET_CHAT_ID}" '${msg}'`; execSync(sendCmd); ``` ### Technical Analysis The scripts interpolate caller-controlled values directly into command strings passed to `child_process.execSync()`. A shell interprets these strings. The affected values include: - `TARGET_CHAT_ID`, obtained from `process.argv[2]`. - Image paths obtained from command-line arguments. - Post content embedded in serialized Feishu messages. - Error text embedded in failure notifications. Double quotation marks do not prevent command substitution in common shells. In addition, the serialized message is enclosed in single quotation marks, but JSON strings can legitimately contain apost ...[truncated 1669 chars]- Remediation
View remediation
