Skip to content

Commit b6127ef

Browse files
mikasa0818claudesteipete
authored
fix(agents): prevent malformed HTML entities from breaking tool calls (#99564)
* Reject surrogate HTML entities in tool args Co-Authored-By: Claude <[email protected]> * docs(changelog): note tool argument entity fix --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
1 parent 49ae7ec commit b6127ef

3 files changed

Lines changed: 11 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai
1919
### Fixes
2020

2121
- **Source build portability:** keep tsdown configuration self-contained so builds do not depend on resolving the tsdown package from unrun's temporary module directory.
22+
- **Agent tool-call decoding:** preserve surrogate-range numeric HTML entities as literal text while still decoding valid supplementary-plane values, preventing malformed model output from injecting lone UTF-16 surrogates into tool arguments. (#99564) Thanks @mikasa0818.
2223
- **Gateway event dispatch:** catch and log lazy subscriber setup and handler failures instead of leaking unhandled promise rejections. (#100401) Thanks @cxbAsDev.
2324
- **Diffs rendering:** render viewer and image output from one SSR preload, preserve language-pack highlighting through hydration, normalize language hints case-insensitively, skip identical before/after inputs with an explicit `changed` result, report truthful file-render and input errors, cache hash-pinned viewer runtimes, and prefer canonical file settings over stale aliases. (#100487)
2425
- **Remote browser reliability:** bound persistent Playwright tab enumeration by the existing remote CDP timeout budget and retire timed-out connection attempts so late completions cannot restore a stuck connection. (#80147, #58968) Thanks @HemantSudarshan and @KeaneYan.

src/agents/embedded-agent-runner/tool-call-argument-decoding.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ describe("decodeHtmlEntitiesInObject", () => {
1111
expect(
1212
decodeHtmlEntitiesInObject({
1313
query: "Rock &amp; Roll &#65; &#39;ok&#39; &#x27;hex&#x27;",
14+
emoji: "ok &#x1F600;",
1415
args: ["--flag=&quot;value&quot;", "&lt;input&gt;"],
1516
nested: { deep: "a &amp; b" },
1617
}),
1718
).toEqual({
1819
query: "Rock & Roll A 'ok' 'hex'",
20+
emoji: "ok 😀",
1921
args: ['--flag="value"', "<input>"],
2022
nested: { deep: "a & b" },
2123
});
@@ -32,10 +34,10 @@ describe("decodeHtmlEntitiesInObject", () => {
3234
it("preserves invalid numeric HTML entities", () => {
3335
expect(
3436
decodeHtmlEntitiesInObject({
35-
query: "bad &#x110000; and &#9999999999;",
37+
query: "bad &#x110000; and &#9999999999; and &#xD800; and &#55296;",
3638
}),
3739
).toEqual({
38-
query: "bad &#x110000; and &#9999999999;",
40+
query: "bad &#x110000; and &#9999999999; and &#xD800; and &#55296;",
3941
});
4042
});
4143
});

src/agents/embedded-agent-runner/tool-call-argument-decoding.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ const HTML_ENTITY_RE = /&(?:amp|lt|gt|quot|apos|#39|#x[0-9a-f]+|#\d+);/i;
1717
function decodeHtmlEntities(value: string): string {
1818
const decodeNumericEntity = (raw: string, radix: 10 | 16): string => {
1919
const codePoint = Number.parseInt(raw, radix);
20-
return Number.isFinite(codePoint) && codePoint >= 0 && codePoint <= 0x10ffff
20+
const isValidCodePoint =
21+
Number.isInteger(codePoint) &&
22+
codePoint >= 0 &&
23+
codePoint <= 0x10ffff &&
24+
(codePoint < 0xd800 || codePoint > 0xdfff);
25+
return isValidCodePoint
2126
? String.fromCodePoint(codePoint)
2227
: `&#${radix === 16 ? "x" : ""}${raw};`;
2328
};

0 commit comments

Comments
 (0)