Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 34 additions & 10 deletions apps/sim/app/chat/components/message/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,44 @@ export const ClientChatMessage = memo(
<div
key={attachment.id}
className={`relative overflow-hidden rounded-2xl border border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800 ${
attachment.dataUrl?.trim() ? 'cursor-pointer' : ''
attachment.dataUrl?.trim() && attachment.dataUrl.startsWith('data:')
? 'cursor-pointer'
: ''
} ${
isImage
? 'h-16 w-16 md:h-20 md:w-20'
: 'flex h-16 min-w-[140px] max-w-[220px] items-center gap-2 px-3 md:h-20 md:min-w-[160px] md:max-w-[240px]'
}`}
onClick={(e) => {
if (attachment.dataUrl?.trim()) {
const validDataUrl = attachment.dataUrl?.trim()
if (validDataUrl?.startsWith('data:')) {
e.preventDefault()
window.open(attachment.dataUrl, '_blank')
e.stopPropagation()
const newWindow = window.open('', '_blank')
if (newWindow) {
newWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>${attachment.name}</title>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: XSS vulnerability: ${attachment.name} is not HTML-escaped. If a user uploads a file named &lt;/title&gt;&lt;script&gt;alert('XSS')&lt;/script&gt;, it will execute JavaScript in the new window.

Suggested change
<title>${attachment.name}</title>
<title>${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}</title>
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/chat/components/message/message.tsx
Line: 105:105

Comment:
**logic:** XSS vulnerability: `${attachment.name}` is not HTML-escaped. If a user uploads a file named `&lt;/title&gt;&lt;script&gt;alert('XSS')&lt;/script&gt;`, it will execute JavaScript in the new window.

```suggestion
                                    <title>${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}</title>
```

How can I resolve this? If you propose a fix, please make it concise.

<style>
body { margin: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #000; }
img { max-width: 100%; max-height: 100vh; object-fit: contain; }
</style>
</head>
<body>
<img src="${validDataUrl}" alt="${attachment.name}" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: XSS vulnerability: ${attachment.name} in the alt attribute is not HTML-escaped.

Suggested change
<img src="${validDataUrl}" alt="${attachment.name}" />
<img src="${validDataUrl}" alt="${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}" />
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/chat/components/message/message.tsx
Line: 112:112

Comment:
**logic:** XSS vulnerability: `${attachment.name}` in the alt attribute is not HTML-escaped.

```suggestion
                                    <img src="${validDataUrl}" alt="${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}" />
```

How can I resolve this? If you propose a fix, please make it concise.

</body>
</html>
`)
newWindow.document.close()
}
}
}}
>
{isImage ? (
{isImage &&
attachment.dataUrl?.trim() &&
attachment.dataUrl.startsWith('data:') ? (
<img
src={attachment.dataUrl}
alt={attachment.name}
Expand Down Expand Up @@ -126,20 +150,20 @@ export const ClientChatMessage = memo(
</div>
)}

<div className='flex justify-end'>
<div className='max-w-[80%] rounded-3xl bg-[#F4F4F4] px-4 py-3 dark:bg-gray-600'>
{/* Render text content if present and not just file count message */}
{message.content && !String(message.content).startsWith('Sent') && (
{/* Only render message bubble if there's actual text content (not just file count message) */}
{message.content && !String(message.content).startsWith('Sent') && (
<div className='flex justify-end'>
<div className='max-w-[80%] rounded-3xl bg-[#F4F4F4] px-4 py-3 dark:bg-gray-600'>
<div className='whitespace-pre-wrap break-words text-base text-gray-800 leading-relaxed dark:text-gray-100'>
{isJsonObject ? (
<pre>{JSON.stringify(message.content, null, 2)}</pre>
) : (
<span>{message.content as string}</span>
)}
</div>
)}
</div>
</div>
</div>
)}
</div>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ export function Chat({ chatMessage, setChatMessage }: ChatProps) {
focusInput(100)
}, [
chatMessage,
chatFiles,
isUploadingFiles,
activeWorkflowId,
isExecuting,
promptHistory,
Expand All @@ -487,6 +489,9 @@ export function Chat({ chatMessage, setChatMessage }: ChatProps) {
appendMessageContent,
finalizeMessageStream,
focusInput,
setChatMessage,
setChatFiles,
setUploadErrors,
])

// Handle key press
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,40 @@ export function ChatMessage({ message }: ChatMessageProps) {
<div
key={attachment.id}
className={`relative overflow-hidden rounded-md border border-border/50 bg-muted/20 ${
attachment.dataUrl?.trim() ? 'cursor-pointer' : ''
attachment.dataUrl?.trim() && attachment.dataUrl.startsWith('data:')
? 'cursor-pointer'
: ''
} ${isImage ? 'h-16 w-16' : 'flex h-16 min-w-[120px] max-w-[200px] items-center gap-2 px-2'}`}
onClick={(e) => {
if (attachment.dataUrl?.trim()) {
const validDataUrl = attachment.dataUrl?.trim()
if (validDataUrl?.startsWith('data:')) {
e.preventDefault()
window.open(attachment.dataUrl, '_blank')
e.stopPropagation()
const newWindow = window.open('', '_blank')
if (newWindow) {
newWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>${attachment.name}</title>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: XSS vulnerability: ${attachment.name} is not HTML-escaped.

Suggested change
<title>${attachment.name}</title>
<title>${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}</title>
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/chat-message/chat-message.tsx
Line: 113:113

Comment:
**logic:** XSS vulnerability: `${attachment.name}` is not HTML-escaped.

```suggestion
                                <title>${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}</title>
```

How can I resolve this? If you propose a fix, please make it concise.

<style>
body { margin: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #000; }
img { max-width: 100%; max-height: 100vh; object-fit: contain; }
</style>
</head>
<body>
<img src="${validDataUrl}" alt="${attachment.name}" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: XSS vulnerability: ${attachment.name} in the alt attribute is not HTML-escaped.

Suggested change
<img src="${validDataUrl}" alt="${attachment.name}" />
<img src="${validDataUrl}" alt="${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}" />
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/chat/components/chat-message/chat-message.tsx
Line: 120:120

Comment:
**logic:** XSS vulnerability: `${attachment.name}` in the alt attribute is not HTML-escaped.

```suggestion
                                <img src="${validDataUrl}" alt="${attachment.name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;')}" />
```

How can I resolve this? If you propose a fix, please make it concise.

</body>
</html>
`)
newWindow.document.close()
}
}
}}
>
{isImage && attachment.dataUrl ? (
{isImage &&
attachment.dataUrl?.trim() &&
attachment.dataUrl.startsWith('data:') ? (
<img
src={attachment.dataUrl}
alt={attachment.name}
Expand Down Expand Up @@ -134,18 +158,18 @@ export function ChatMessage({ message }: ChatMessageProps) {
</div>
)}

<div className='flex justify-end'>
<div className='max-w-[80%]'>
<div className='rounded-[10px] bg-secondary px-3 py-2'>
{/* Render text content if present and not just file count message */}
{formattedContent && !formattedContent.startsWith('Uploaded') && (
{/* Only render message bubble if there's actual text content (not just file count message) */}
{formattedContent && !formattedContent.startsWith('Uploaded') && (
<div className='flex justify-end'>
<div className='max-w-[80%]'>
<div className='rounded-[10px] bg-secondary px-3 py-2'>
<div className='whitespace-pre-wrap break-words font-normal text-foreground text-sm leading-normal'>
<WordWrap text={formattedContent} />
</div>
)}
</div>
</div>
</div>
</div>
)}
</div>
)
}
Expand Down