T09 · Insecure Skill Coding Practices
Warning
- Location
- assets/scripts/html-to-pptx.js:113
- Finding
- Unrestricted Local Image Paths Can Disclose Local Files<![CDATA[ ## Vulnerability Details **File Location**: `assets/scripts/html-to-pptx.js:113-121, 540-551` **Vulnerability Type**: Unrestricted local file access through attacker-controlled image paths **Risk Level**: Medium ### Vulnerable Code ```javascript function extractImages(slideHtml) { const images = []; const regex = /<img[^>]*src="([^"]+)"[^>]*>/g; let match; while ((match = regex.exec(slideHtml)) !== null) { if (!match[1].includes('cover_bg') && !match[1].includes('end_bg')) { images.push(match[1]); } } return images; } ``` ```javascript function addImages(slide, images, imgBasePath) { const imgX = 5.0, imgY = 1.1, imgW = 4.7, imgH = 4.0; const validImages = images.filter(p => fs.existsSync(p)); if (validImages.length > 0) { if (validImages.length === 1) { slide.addImage({ path: validImages[0], x: imgX, y: imgY, w: imgW, h: imgH, sizing: { type: 'contain', w: imgW, h: imgH } }); ``` ### Technical Analysis The converter extracts image paths directly from input HTML and treats each extracted value as a local filesystem path. The only validation is `fs.existsSync()`, which confirms that the process can access the path but does not establish that access is authorized. The supplied `imgBasePath` is not used to constrain these image paths. Absolute paths, traversal paths, and paths resolving through symbolic links can therefore refer to files outside the intended working directory. If such a file is a supported image, `pptxgenjs` embeds it in the generated presentation. This violates the documented least-privilege expectation that only user-specified files and Skill resources are read. ### Attack Path 1. An attacker supplies or influences the HTML processed by `html-to-pptx.js`. 2. The HTML contains an image reference to a readable local file, for example: ```html <img src="/path/to/sensitive/local/image.png"> ``` 3. `extractImages()` copies the path without canonicalizat ...[truncated 851 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Resolve every local image path to a canonical absolute path before use: ```javascript const allowedRoot = fs.realpathSync(imgBasePath); const candidate = fs.realpathSync(path.resolve(imgBasePath, imagePath)); ``` 2. Verify that the canonical candidate remains inside the approved root: ```javascript const relative = path.relative(allowedRoot, candidate); if (relative.startsWith('..') || path.isAbsolute(relative)) { throw new Error('Image path is outside the approved directory'); } ``` 3. Reject absolute paths unless the user explicitly approves each path. 4. Resolve real paths before validation to prevent symbolic-link escapes. 5. Allow only expected file extensions and verify file signatures rather than trusting extensions. 6. Apply file-size and image-dimension limits before passing content to `pptxgenjs`. 7. Use `imgBasePath` as an actual security boundary rather than only as a source for cover and end backgrounds. 8. Record rejected paths without exposing unnecessary local filesystem details in user-facing error messages. ]]>
