T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- core.mjs:244
- Finding
- Unrestricted Local File Read Through Image Editing Input<![CDATA[ ## Vulnerability Details **File Location**: `core.mjs:244-260` **Vulnerability Type**: Arbitrary local file read and resource exhaustion **Risk Level**: Medium ### Vulnerable Code ```javascript if (!prompt) throw new Error('prompt is required'); if (!image) throw new Error('image is required (URL or base64 data URI)'); const images = Array.isArray(image) ? image : [image]; if (images.length > 3) throw new Error('Maximum 3 source images'); // Build input with image(s) + text prompt const content = []; for (const img of images) { // If it looks like a file path, read and base64 encode let imageUrl = img; if (!img.startsWith('http') && !img.startsWith('data:')) { const data = readFileSync(img); const ext = img.split('.').pop().toLowerCase(); const mime = ext === 'png' ? 'image/png' : ext === 'webp' ? 'image/webp' : 'image/jpeg'; imageUrl = `data:${mime};base64,${data.toString('base64')}`; } content.push({ type: 'image_url', image_url: { url: imageUrl } }); } ``` ### Technical Analysis The `edit_image` function interprets every string that does not begin with `http` or `data:` as a local filesystem path. It then passes that attacker-controlled path directly to `readFileSync`. No security boundary is enforced around the path. In particular, the implementation does not: - Restrict access to an approved image directory. - Resolve and validate canonical paths. - prevent directory traversal or absolute paths. - Reject symbolic links or non-regular files. - Verify that the content is actually a supported image. - Limit the maximum file size before loading the entire file into memory. The function is reachable through the MCP tool handler in `mcp-server.mjs:132-134`, where caller-provided parameters are forwarded directly to `edit_image`: ```javascript case 'grok_edit_image': result = await edit_image(params); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; ``` The MCP schema describes the ...[truncated 2492 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Separate remote and local image interfaces** - Make the MCP-facing function accept only validated HTTPS URLs or image data URIs. - If local-file editing is needed by the CLI, implement it as a separate local-only function requiring an explicit file option. 2. **Reject unsupported URI schemes and ambiguous strings** - Parse URLs with the standard `URL` class. - Allow only `https:` for remote images. - Validate data URIs against an allowlist such as `image/jpeg`, `image/png`, and `image/webp`. - Reject plain paths in the MCP handler before calling the core function. 3. **Constrain permitted local files** - Resolve paths with `realpath` and require them to remain under a configured upload directory. - Reject traversal outside that directory. - Use `lstat` and reject symbolic links, devices, FIFOs, sockets, and other non-regular files. - Run the MCP process under a dedicated account with minimal filesystem permissions. 4. **Validate file content and size** - Check file size before reading it and enforce a conservative maximum. - Verify image magic bytes instead of relying on the filename extension. - Avoid synchronous whole-file reads in a long-running MCP process. 5. **Correct the request construction** - The constructed `content` array is currently unused. Remove the local read and unused encoding logic if the xAI endpoint expects the original image value. - If encoded image content is intentionally required, send only content that has passed all path, type, and size checks, and clearly disclose that local media will be transmitted to xAI. 6. **Harden the MCP schema and handler** - Add enforceable format constraints where supported. - Perform runtime validation regardless of schema declarations. - Return a generic validation error that does not distinguish nonexistent, inaccessible, or disallowed local paths. ]]>
