fix(image-uris): resolve review-bot issues

ClineProvider.convertToWebviewUri: align JSDoc with non-throwing behavior and fallback to file URI.

imageDataUrl.webviewUriToFilePath: remove impossible CDN host check from vscode-resource branch; expand Windows path regex to allow spaces while keeping bounds.

ChatTextArea: clear pendingImageUploadsRef via captured ref in cleanup to avoid stale closure.
This commit is contained in:
daniel-lxs 2025-10-27 20:30:25 -05:00
parent 9dc853cf7f
commit 634ee677d9
No known key found for this signature in database
GPG key ID: 21C74479048B3AA6
3 changed files with 14 additions and 23 deletions

View file

@ -2790,13 +2790,11 @@ export class ClineProvider
}
/**
* Convert a file path to a webview-accessible URI
* This method safely converts file paths to URIs that can be loaded in the webview
* Convert a file path to a webview-accessible URI.
* Safely returns a string and does not throw; logs errors and falls back to a file: URI when conversion is not possible.
*
* @param filePath - The absolute file path to convert
* @returns The webview URI string, or the original file URI if conversion fails
* @throws {Error} When webview is not available
* @throws {TypeError} When file path is invalid
* @returns The webview URI string when a webview is available; otherwise a file: URI string
*/
public convertToWebviewUri(filePath: string): string {
try {

View file

@ -73,10 +73,7 @@ function webviewUriToFilePath(webviewUri: string): string {
// Handle VS Code webview URIs that contain encoded paths
// Use strict prefix matching to prevent arbitrary host injection
if (
webviewUri.startsWith("vscode-resource://vscode-webview/") &&
(webviewUri.includes("vscode-userdata") || isValidVsCodeCdnHost(webviewUri))
) {
if (webviewUri.startsWith("vscode-resource://vscode-webview/") && webviewUri.includes("vscode-userdata")) {
try {
// Decode safely with length limits
if (webviewUri.length > 2048) {
@ -94,7 +91,7 @@ function webviewUriToFilePath(webviewUri: string): string {
return unixMatch[0]
}
const windowsMatch = decoded.match(/^[^?#]*C:\\[a-zA-Z0-9._\\-]{1,300}\.(png|jpg|jpeg|gif|webp)$/i)
const windowsMatch = decoded.match(/^[^?#]*[A-Za-z]:\\[^?#]{1,300}\.(png|jpg|jpeg|gif|webp)$/i)
if (windowsMatch) {
return windowsMatch[0]
}
@ -110,19 +107,6 @@ function webviewUriToFilePath(webviewUri: string): string {
/**
* Gets the MIME type from a file path
*/
/**
* Safely validates if a webview URI is from the trusted vscode-cdn.net host
* Prevents host injection attacks by properly parsing the URL
*/
function isValidVsCodeCdnHost(webviewUri: string): boolean {
try {
const url = new URL(webviewUri)
return url.host === "vscode-cdn.net"
} catch {
// URL parsing failed - not a valid URL
return false
}
}
function getMimeTypeFromPath(filePath: string): string {
const ext = path.extname(filePath).toLowerCase()

View file

@ -652,6 +652,15 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
// This ensures the frontend never retains image data URLs
const pendingImageUploadsRef = useRef<Set<string>>(new Set())
// Cleanup pending uploads on unmount to prevent leaks
useEffect(() => {
// Capture ref value to avoid stale closure
const uploads = pendingImageUploadsRef.current
return () => {
uploads.clear()
}
}, [])
const handlePaste = useCallback(
async (e: React.ClipboardEvent) => {
const items = e.clipboardData.items