mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
harden: restrict markdown link schemes; parse untrusted XML with defusedxml
Two small defensive-hardening changes: - web/src/components/Markdown.tsx: render links only for http(s)/mailto schemes; other schemes (javascript:, data:, vbscript:) are dropped to plain text so a crafted link in rendered content can't execute on click. - gateway/platforms/wecom_callback.py: parse the untrusted, pre-auth WeCom callback request body with defusedxml instead of xml.etree, blocking entity-expansion / billion-laughs (and XXE) on the parse path. defusedxml is already a dependency (uv.lock); response-building XML in wecom_crypto.py is unchanged (it is not parsed from untrusted input). Verified: dashboard typechecks and builds; defusedxml blocks an entity-expansion payload while valid WeCom envelopes still parse.
This commit is contained in:
parent
f4953bc648
commit
5744b17579
2 changed files with 21 additions and 3 deletions
|
|
@ -17,7 +17,11 @@ import logging
|
|||
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
|
||||
|
|
|
|||
|
|
@ -324,11 +324,24 @@ 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"
|
||||
|
|
@ -336,6 +349,7 @@ function InlineContent({
|
|||
{node.text}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
case "br":
|
||||
return <br key={i} />;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue