T09 · Insecure Skill Coding Practices
- Location
scripts/send-media.mjs:8- Finding
Unrestricted Local File Upload to an Attacker-Controlled Feishu Recipient
- Content
View full analysis
[file_type] [duration_ms]'); const APP_SECRET = fs.readFileSync(APP_SECRET_PATH, 'utf8').trim(); const client = new Lark.Client({ appId: APP_ID, appSecret: APP_SECRET, domain: Lark.Domain.Feishu, appType: Lark.AppType.SelfBuild, }); const fileStream = fs.createReadStream(FILE_PATH); const fileName = FILE_PATH.split('/').pop(); const data = { file_type: FILE_TYPE, file_name: fileName, file: fileStream, }; if (DURATION_MS) data.duration = Number(DURATION_MS); const uploadRes = await client.im.v1.file.create({ data }); console.log('UPLOAD_RES', JSON.stringify(uploadRes, null, 2)); const fileKey = uploadRes.data?.file_key || uploadRes.file_key; if (!fileKey) throw new Error('no file_key returned'); const sendRes = await client.im.v1.message.create({ params: { receive_id_type: 'open_id' }, data: { receive_id: RECEIVE_ID, msg_type: 'media', content: JSON.stringify({ file_key: fileKey }), }, }); ``` ### Technical Analysis The script is documented as an MP4 delivery utility, but it accepts an arbitrary filesystem path through `process.argv[3]` and an arbitrary file type through `process.argv[4]`. The file type defaults to the generic value `stream`. The path is passed directly to `fs.createReadStream()` without any of the following controls: - Canonical-path validation - Restriction to an approved media output directory - File extension or MIME-type validation - Media signature verification - Regular-file verifica ...[truncated 2005 chars]- Remediation
View remediation
