mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
fix: add URL sanitization to prevent XSS and redirect vulnerabilities in Thumbnails component
This commit is contained in:
parent
bf3adfc258
commit
d75f8649b1
1 changed files with 72 additions and 42 deletions
|
|
@ -36,6 +36,28 @@ const Thumbnails = ({ images, style, setImages, onHeightChange }: ThumbnailsProp
|
|||
vscode.postMessage({ type: "openImage", text: image })
|
||||
}
|
||||
|
||||
// Sanitize image URL to prevent XSS and malicious redirects
|
||||
const sanitizeImageUrl = (url: string): string => {
|
||||
try {
|
||||
// Only allow data URLs (base64 images) and https URLs
|
||||
if (url.startsWith("data:image/")) {
|
||||
return url
|
||||
}
|
||||
|
||||
// For other URLs, validate they are safe
|
||||
const parsedUrl = new URL(url)
|
||||
if (parsedUrl.protocol === "https:" || parsedUrl.protocol === "http:") {
|
||||
return url
|
||||
}
|
||||
|
||||
// Reject any other protocols (javascript:, file:, etc.)
|
||||
return ""
|
||||
} catch {
|
||||
// Invalid URL, return empty string
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
|
|
@ -46,51 +68,59 @@ const Thumbnails = ({ images, style, setImages, onHeightChange }: ThumbnailsProp
|
|||
rowGap: 3,
|
||||
...style,
|
||||
}}>
|
||||
{images.map((image, index) => (
|
||||
<div
|
||||
key={index}
|
||||
style={{ position: "relative" }}
|
||||
onMouseEnter={() => setHoveredIndex(index)}
|
||||
onMouseLeave={() => setHoveredIndex(null)}>
|
||||
<img
|
||||
src={image}
|
||||
alt={`Thumbnail ${index + 1}`}
|
||||
style={{
|
||||
width: 34,
|
||||
height: 34,
|
||||
objectFit: "cover",
|
||||
borderRadius: 4,
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => handleImageClick(image)}
|
||||
/>
|
||||
{isDeletable && hoveredIndex === index && (
|
||||
<div
|
||||
onClick={() => handleDelete(index)}
|
||||
{images.map((image, index) => {
|
||||
const sanitizedUrl = sanitizeImageUrl(image)
|
||||
// Skip rendering if URL is invalid/unsafe
|
||||
if (!sanitizedUrl) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
style={{ position: "relative" }}
|
||||
onMouseEnter={() => setHoveredIndex(index)}
|
||||
onMouseLeave={() => setHoveredIndex(null)}>
|
||||
<img
|
||||
src={sanitizedUrl}
|
||||
alt={`Thumbnail ${index + 1}`}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: -4,
|
||||
right: -4,
|
||||
width: 13,
|
||||
height: 13,
|
||||
borderRadius: "50%",
|
||||
backgroundColor: "var(--vscode-badge-background)",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: 34,
|
||||
height: 34,
|
||||
objectFit: "cover",
|
||||
borderRadius: 4,
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<span
|
||||
className="codicon codicon-close"
|
||||
}}
|
||||
onClick={() => handleImageClick(image)}
|
||||
/>
|
||||
{isDeletable && hoveredIndex === index && (
|
||||
<div
|
||||
onClick={() => handleDelete(index)}
|
||||
style={{
|
||||
color: "var(--vscode-foreground)",
|
||||
fontSize: 10,
|
||||
fontWeight: "bold",
|
||||
}}></span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
position: "absolute",
|
||||
top: -4,
|
||||
right: -4,
|
||||
width: 13,
|
||||
height: 13,
|
||||
borderRadius: "50%",
|
||||
backgroundColor: "var(--vscode-badge-background)",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<span
|
||||
className="codicon codicon-close"
|
||||
style={{
|
||||
color: "var(--vscode-foreground)",
|
||||
fontSize: 10,
|
||||
fontWeight: "bold",
|
||||
}}></span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue