T09 · Insecure Skill Coding Practices
- Location
src/services/media.ts:1022- Finding
Arbitrary Local File Disclosure Through Agent-Generated Paths
- Content
View full analysis
{ const logPrefix = 'RawMedia'; const rawPathPattern = /(?:^|\s)((?:[A-Za-z]:)?[\/\\](?:[^\/\\:\*\?"<>\|\s]+[\/\\])*[^\/\\:\*\?"<>\|\s]+\.(?:mp4|avi|mov|wmv|flv|mkv|webm|mp3|wav|flac|aac|ogg|m4a|wma|pdf|doc|docx|xls|xlsx|ppt|pptx|txt|zip|rar|7z|tar|gz))(?:\s|$)/gi; const matches = Array.from(content.matchAll(rawPathPattern)); if (matches.length === 0) { return content; } for (const match of matches) { const fullMatch = match[0]; const filePath = match[1].trim(); const uploadResult = await uploadMediaToDingTalk( filePath, mediaType, oapiToken, 20 * 1024 * 1024, log ); ``` The upload implementation accepts the supplied path without restricting it to an approved workspace: ```ts const absPath = toLocalPath(filePath); log?.info?.(`检查文件是否存在:${absPath}`); if (!fs.existsSync(absPath)) { log?.warn?.(`文件不存在:${absPath}`); return null; } const stats = fs.statSync(absPath); const form = new FormData(); form.append('media', fs.createReadStream(absPath), { filename: path.basename(absPath), contentType: mediaType === 'image' ? 'image/jpeg' : 'application/octet-stream', }); const resp = await dingtalkUploadHttp.post( `${DINGTALK_OAPI}/media/upload`, form, { params: { access_token: oapiToken, type: mediaType }, headers: form.getHeaders(), timeout: 60_000, maxBodyLength: Infinity, }, ); ``` ### Technical Analysis The connector scans agent-generated response text for absolute local paths with ...[truncated 2246 chars]- Remediation
View remediation
