T09 · Insecure Skill Coding Practices
- Location
src/index.ts:95- Finding
Unrestricted Server-Side URL Fetching Enables SSRF and Data Disclosure
- Content
View full analysis
{ if (!/^https?:\/\//.test(url)) return null; try { const resp = await fetch(url, { signal: AbortSignal.timeout(30000), redirect: 'follow' }); if (!resp.ok) return null; const contentType = resp.headers.get('content-type') || 'application/octet-stream'; const contentLength = parseInt(resp.headers.get('content-length') || '0'); if (contentLength > MAX_DOWNLOAD_SIZE) { console.warn(`[download] Too large: ${contentLength}`); return null; } const arrayBuffer = await resp.arrayBuffer(); if (arrayBuffer.byteLength > MAX_DOWNLOAD_SIZE) return null; return { buffer: Buffer.from(arrayBuffer), mimeType: contentType.split(';')[0].trim() }; } catch (e) { console.error(`[download] Failed: ${url}`, e); return null; } } ``` The URL is reached through the media-delivery handler: ```ts if (source_url) { const downloaded = await downloadFromUrl(source_url); if (downloaded) { buffer = downloaded.buffer; mimeType = downloaded.mimeType || ct; } } ``` PDF image embedding exposes an equivalent request surface: ```ts const allImages = extractImages(content); const imageCache = new Map(); if (allImages.length > 0) { await Promise.allSettled( allImages.slice(0, 10).map(async (img) => { const data = await downloadImage(img.url); if (data) imageCache.set(img.url, data); }) ); } ``` ### Technical Analysis The Skill accepts URLs controlled through `source_url` or embedded Markdown image references and fetches them from the server-side runtime. Validation only checks whether a URL begins with `http://` or `https://`. The implementation doe ...[truncated 2485 chars]- Remediation
View remediation
