Skip to content
Merged

Test #87

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
5 changes: 4 additions & 1 deletion lib/emails/inbound/generateEmailResponse.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { marked } from "marked";
import { ChatRequestBody } from "@/lib/chat/validateChatRequest";
import getGeneralAgent from "@/lib/agents/generalAgent/getGeneralAgent";
import { getEmailRoomMessages } from "@/lib/emails/inbound/getEmailRoomMessages";
Expand Down Expand Up @@ -27,6 +28,8 @@ export async function generateEmailResponse(
const chatResponse = await agent.generate({ messages });
const text = chatResponse.text;

const bodyHtml = marked(text);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Potential XSS vulnerability from unsanitized HTML rendering.

Using marked(text) without sanitization allows HTML passthrough by default. If the AI-generated text contains malicious HTML or JavaScript, it will be rendered directly in the email, creating an XSS attack vector.

🔎 Recommended fix to sanitize HTML output

Configure marked with the sanitize or mangle options, or use a dedicated sanitization library like DOMPurify:

-  const bodyHtml = marked(text);
+  const bodyHtml = marked(text, { 
+    mangle: false, 
+    headerIds: false,
+    breaks: true 
+  });
+  // Consider additional sanitization with DOMPurify or similar

Alternatively, use marked.parse() with explicit renderer configuration to strip or escape HTML tags.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @lib/emails/inbound/generateEmailResponse.ts around line 31, Sanitize the
HTML output from marked by passing the rendered string through a sanitizer
instead of using marked(text) directly: replace the direct call to produce
bodyHtml with a safe pipeline like bodyHtml = DOMPurify.sanitize(marked(text))
(importing an appropriate server-safe sanitizer such as isomorphic-dompurify or
DOMPurify), or configure marked to disallow HTML and escape tags via a custom
renderer before assigning to bodyHtml; ensure you reference the same variable
names (bodyHtml and text) and the marked(text) call when making the change.


const footerHtml = `
<hr style="margin-top:24px;margin-bottom:16px;border:none;border-top:1px solid #e5e7eb;" />
<p style="font-size:12px;color:#6b7280;margin:0 0 4px;">
Expand All @@ -40,7 +43,7 @@ export async function generateEmailResponse(
</p>
`.trim();

const html = `${text}\n\n${footerHtml}`;
const html = `${bodyHtml}\n\n${footerHtml}`;

return { text, html };
}
2 changes: 2 additions & 0 deletions lib/emails/inbound/respondToInboundEmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export async function respondToInboundEmail(
const to = original.from;
const toArray = [to];
const from = getFromWithName(original.to, original.cc);
const cc = original.cc?.length ? original.cc : undefined;

// Validate new memory and get chat request body (or early return if duplicate)
const validationResult = await validateNewEmailMemory(event);
Expand All @@ -48,6 +49,7 @@ export async function respondToInboundEmail(
const payload = {
from,
to: toArray,
...(cc && { cc }),
subject,
html,
headers: {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"bullmq": "^5.65.1",
"googleapis": "^168.0.0",
"ioredis": "^5.8.2",
"marked": "^15.0.12",
"mcp-handler": "^1.0.4",
"multiformats": "^13.4.1",
"next": "^16.0.7",
Expand Down
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.