🐛 fix(chatMessage): sanitize HTML content to prevent potential XSS attacks
✨ feat(chatMessage): improve rendering of multi-line messages
The `convert` variable is now imported before being used to convert ANSI to HTML. Additionally, the `DOMPurify` library is imported and used to sanitize the HTML content before rendering it, preventing potential XSS attacks. The rendering of multi-line messages has been improved by splitting the message by newline characters and rendering each line separately with a line break.
This commit is contained in:
parent
e1bf25a4ff
commit
3faf5f5b96
2 changed files with 14 additions and 14 deletions
|
|
@ -2,9 +2,9 @@ import { useState } from "react";
|
||||||
import { ChatMessageType } from "../../../types/chat";
|
import { ChatMessageType } from "../../../types/chat";
|
||||||
import { nodeColors } from "../../../utils";
|
import { nodeColors } from "../../../utils";
|
||||||
import Convert from "ansi-to-html";
|
import Convert from "ansi-to-html";
|
||||||
const convert = new Convert({ newline: true });
|
|
||||||
import { MessageCircle } from "lucide-react";
|
import { MessageCircle } from "lucide-react";
|
||||||
|
import DOMPurify from "dompurify";
|
||||||
|
const convert = new Convert({ newline: true });
|
||||||
export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
||||||
const [hidden, setHidden] = useState(true);
|
const [hidden, setHidden] = useState(true);
|
||||||
return (
|
return (
|
||||||
|
|
@ -23,13 +23,14 @@ export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
|
||||||
<MessageCircle className="w-5 h-5 animate-bounce" />
|
<MessageCircle className="w-5 h-5 animate-bounce" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{chat.thought && chat.thought !== "" && !hidden && (
|
{chat.thought && chat.thought !== "" && !hidden && (
|
||||||
<div
|
<div
|
||||||
onClick={() => setHidden((prev) => !prev)}
|
onClick={() => setHidden((prev) => !prev)}
|
||||||
style={{ backgroundColor: nodeColors["thought"] }}
|
style={{ backgroundColor: nodeColors["thought"] }}
|
||||||
className="text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer"
|
className="text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: convert.toHtml(chat.thought),
|
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import remarkMath from "remark-math";
|
||||||
import { CodeBlock } from "./codeBlock";
|
import { CodeBlock } from "./codeBlock";
|
||||||
import Convert from "ansi-to-html";
|
import Convert from "ansi-to-html";
|
||||||
import { User2, MessageCircle } from "lucide-react";
|
import { User2, MessageCircle } from "lucide-react";
|
||||||
|
import DOMPurify from "dompurify";
|
||||||
export default function ChatMessage({
|
export default function ChatMessage({
|
||||||
chat,
|
chat,
|
||||||
lockChat,
|
lockChat,
|
||||||
|
|
@ -78,10 +78,9 @@ export default function ChatMessage({
|
||||||
{chat.thought && chat.thought !== "" && !hidden && (
|
{chat.thought && chat.thought !== "" && !hidden && (
|
||||||
<div
|
<div
|
||||||
onClick={() => setHidden((prev) => !prev)}
|
onClick={() => setHidden((prev) => !prev)}
|
||||||
className=" text-start inline-block rounded-md text-gray-600 dark:text-gray-200 h-full border border-gray-300 dark:border-gray-500
|
className="text-start inline-block rounded-md text-gray-600 dark:text-gray-200 h-full border border-gray-300 dark:border-gray-500 bg-muted dark:bg-gray-800 w-[95%] pb-3 pt-3 px-2 ml-3 cursor-pointer scrollbar-hide overflow-scroll"
|
||||||
bg-muted dark:bg-gray-800 w-[95%] pb-3 pt-3 px-2 ml-3 cursor-pointer scrollbar-hide overflow-scroll"
|
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: convert.toHtml(chat.thought),
|
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -152,12 +151,12 @@ export default function ChatMessage({
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full flex items-center">
|
<div className="w-full flex items-center">
|
||||||
<div className="text-start inline-block px-3 text-gray-600 dark:text-white">
|
<div className="text-start inline-block px-3 text-gray-600 dark:text-white">
|
||||||
<span
|
{message.split("\n").map((line, index) => (
|
||||||
className="text-gray-600 dark:text-gray-200"
|
<span key={index}>
|
||||||
dangerouslySetInnerHTML={{
|
{line}
|
||||||
__html: message.replace(/\n/g, "<br>"),
|
<br />
|
||||||
}}
|
</span>
|
||||||
></span>
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue