Skip to content
Closed
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
6 changes: 5 additions & 1 deletion gateway/platforms/wecom_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
import socket as _socket
import time
from typing import Any, Dict, List, Optional
from xml.etree import ElementTree as ET
# Security: parse untrusted, pre-auth request bodies (WeCom callbacks) with
# defusedxml to block billion-laughs / entity-expansion (and XXE) DoS. The
# parsing API (fromstring) is a drop-in for the stdlib calls used below;
# response-building XML lives in wecom_crypto.py and is not parsed here.
import defusedxml.ElementTree as ET

try:
from aiohttp import web
Expand Down
18 changes: 16 additions & 2 deletions web/src/components/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -324,18 +324,32 @@ function InlineContent({
<HighlightedText text={node.content} terms={highlightTerms} />
</em>
);
case "link":
case "link": {
// Security: only render http(s)/mailto links. Other schemes
// (javascript:, data:, vbscript:) are dropped to plain text so a
// crafted link in agent/message content can't execute on click.
const href = node.href.trim();
if (!/^(https?:|mailto:)/i.test(href)) {
return (
<HighlightedText
key={i}
text={node.text}
terms={highlightTerms}
/>
);
}
return (
<a
key={i}
href={node.href}
href={href}
target="_blank"
rel="noreferrer"
className="text-primary underline underline-offset-2 decoration-primary/30 hover:decoration-primary/60 transition-colors"
>
{node.text}
</a>
);
}
case "br":
return <br key={i} />;
}
Expand Down