mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-30 03:11:10 +00:00
matrix: guard invalid HTML entity mention labels
This commit is contained in:
@@ -209,6 +209,37 @@ describe("resolveMentions", () => {
|
||||
expect(result.wasMentioned).toBe(true);
|
||||
});
|
||||
|
||||
it("ignores out-of-range hexadecimal HTML entities in visible labels", () => {
|
||||
expect(() =>
|
||||
resolveMentions({
|
||||
content: {
|
||||
msgtype: "m.text",
|
||||
body: "hello",
|
||||
formatted_body: '<a href="https://matrix.to/#/@bot:matrix.org">�</a>: hello',
|
||||
},
|
||||
userId,
|
||||
text: "hello",
|
||||
mentionRegexes: [],
|
||||
}),
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it("ignores oversized decimal HTML entities in visible labels", () => {
|
||||
expect(() =>
|
||||
resolveMentions({
|
||||
content: {
|
||||
msgtype: "m.text",
|
||||
body: "hello",
|
||||
formatted_body:
|
||||
'<a href="https://matrix.to/#/@bot:matrix.org">�</a>: hello',
|
||||
},
|
||||
userId,
|
||||
text: "hello",
|
||||
mentionRegexes: [],
|
||||
}),
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it("does not detect mention when displayName is spoofed", () => {
|
||||
const result = resolveMentions({
|
||||
content: {
|
||||
|
||||
@@ -9,17 +9,29 @@ const HTML_ENTITY_REPLACEMENTS: Readonly<Record<string, string>> = {
|
||||
nbsp: " ",
|
||||
quot: '"',
|
||||
};
|
||||
const MAX_UNICODE_SCALAR_VALUE = 0x10ffff;
|
||||
|
||||
function decodeNumericHtmlEntity(match: string, rawValue: string, radix: 10 | 16): string {
|
||||
const codePoint = Number.parseInt(rawValue, radix);
|
||||
if (
|
||||
!Number.isSafeInteger(codePoint) ||
|
||||
codePoint < 0 ||
|
||||
codePoint > MAX_UNICODE_SCALAR_VALUE ||
|
||||
(codePoint >= 0xd800 && codePoint <= 0xdfff)
|
||||
) {
|
||||
return match;
|
||||
}
|
||||
return String.fromCodePoint(codePoint);
|
||||
}
|
||||
|
||||
function decodeHtmlEntities(value: string): string {
|
||||
return value.replace(/&(#x?[0-9a-f]+|\w+);/gi, (match, entity: string) => {
|
||||
const normalized = entity.toLowerCase();
|
||||
if (normalized.startsWith("#x")) {
|
||||
const codePoint = Number.parseInt(normalized.slice(2), 16);
|
||||
return Number.isNaN(codePoint) ? match : String.fromCodePoint(codePoint);
|
||||
return decodeNumericHtmlEntity(match, normalized.slice(2), 16);
|
||||
}
|
||||
if (normalized.startsWith("#")) {
|
||||
const codePoint = Number.parseInt(normalized.slice(1), 10);
|
||||
return Number.isNaN(codePoint) ? match : String.fromCodePoint(codePoint);
|
||||
return decodeNumericHtmlEntity(match, normalized.slice(1), 10);
|
||||
}
|
||||
return HTML_ENTITY_REPLACEMENTS[normalized] ?? match;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user