T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/lib/providers.mjs:33
- Finding
- Unrestricted Local File Reading and Transmission to External Providers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib/providers.mjs:33-43` **Vulnerability Type**: Arbitrary local file disclosure through unrestricted image inputs **Risk Level**: High ### Vulnerable Code ```js async function asBase64(p) { if (isUrl(p)) { const r = await fetch(p) if (!r.ok) throw new Error(`拉取参考图失败 ${r.status}: ${p}`) return Buffer.from(await r.arrayBuffer()).toString('base64') } return (await readFile(p)).toString('base64') } const asDataUri = async (p) => isUrl(p) ? p : `data:${mimeOf(p)};base64,${await asBase64(p)}` ``` The same unrestricted file-reading behavior is used by multiple outbound provider implementations, including: - OpenAI: `scripts/lib/providers.mjs:143-155` - Gemini: `scripts/lib/providers.mjs:198-211` - fal: `scripts/lib/providers.mjs:233-240` - Replicate: `scripts/lib/providers.mjs:262-269` - Ark: `scripts/lib/providers.mjs:294-302` ### Technical Analysis The `--images` command-line argument accepts arbitrary strings and passes them to provider implementations without validating that each path identifies an authorized image file. When an input is not recognized as an HTTP or HTTPS URL, `asBase64()` reads the path directly using `readFile()`. There is no enforcement of: - An approved input directory - Canonical path containment - Symbolic-link containment - Allowed file extensions - Image magic bytes - MIME type correctness - Maximum file size - The documented 20 KB to 15 MB limit - The documented JPG, JPEG, PNG, and WebP format restriction The `mimeOf()` helper also defaults unknown extensions to `image/jpeg`. Consequently, a non-image file can be labeled as an image, encoded as a data URI, and included in an outbound request. This behavior exceeds the minimum file-access privileges needed to generate an ecommerce image. The Skill only needs access to product and reference images selected by the user, not every file readable by the executing account. Although transmitting intend ...[truncated 1691 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Resolve every local path to its canonical absolute path before reading it. 2. Restrict image inputs to explicitly approved workspace or media directories. 3. Reject paths whose canonical form escapes the approved roots. 4. Resolve symbolic links and reject links that point outside approved directories. 5. Require explicit user confirmation before reading files outside the project workspace. 6. Allow only the documented JPG, JPEG, PNG, and WebP extensions. 7. Inspect file signatures rather than trusting extensions or supplied MIME types. 8. Decode image metadata and verify that the input is a valid image. 9. Enforce the documented file-size and dimension limits before reading the complete file or making a network request. 10. Reject unknown formats instead of defaulting them to `image/jpeg`. 11. Present the canonical paths and destination provider during dry-run and before upload. 12. Consider accepting opened file handles from a trusted media-selection layer instead of arbitrary path strings. 13. Add tests covering sensitive paths, path traversal, absolute paths, symbolic-link escapes, extension spoofing, and oversized files. ]]>
