fix(duckduckgo): decode & last in decodeHtmlEntities to avoid double-decoding#96348
Conversation
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. Keep open: current main and latest release still have the DuckDuckGo amp-first decoder, while this PR fixes a real user-visible result-text corruption with no blocking review findings. Canonical path: Close this PR as superseded by #39. So I’m closing this here and keeping the remaining discussion on #39. Review detailsBest possible solution: Close this PR as superseded by #39. Do we have a high-confidence way to reproduce the issue? Yes. Current main and v2026.6.10 decode Is this the best way to solve the issue? Yes. The best fix is plugin-local: repair Security review: Security review cleared: The diff only changes local string decoding and a focused test, with no dependency, lockfile, CI, secret, install, or code-execution surface change. AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against 2aa9d6763564. |
…ble-decoding decodeHtmlEntities decoded & FIRST, so result text that literally contains an entity (e.g. a page title 'How to escape < in HTML', which DuckDuckGo returns double-encoded as '&lt;') was re-decoded into markup: '&lt;' became '<' instead of the literal '<', corrupting the titles, snippets, and URLs the web-search tool returns to the model. Reorder so & is decoded last, matching the established convention elsewhere in the codebase (msteams/inbound.ts, openai-transport-stream.ts, launchd-plist.ts, doctor-session-snapshots.ts all decode & last). Behavior-preserving for all singly-encoded input. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
281b928 to
2f8d32c
Compare
|
Merged via squash.
|
…ble-decoding (openclaw#96348) * fix(duckduckgo): decode & last in decodeHtmlEntities to avoid double-decoding decodeHtmlEntities decoded & FIRST, so result text that literally contains an entity (e.g. a page title 'How to escape < in HTML', which DuckDuckGo returns double-encoded as '&lt;') was re-decoded into markup: '&lt;' became '<' instead of the literal '<', corrupting the titles, snippets, and URLs the web-search tool returns to the model. Reorder so & is decoded last, matching the established convention elsewhere in the codebase (msteams/inbound.ts, openai-transport-stream.ts, launchd-plist.ts, doctor-session-snapshots.ts all decode & last). Behavior-preserving for all singly-encoded input. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * fix(duckduckgo): decode html entities in one pass --------- Co-authored-by: ly-wang19 <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> Co-authored-by: Vincent Koc <[email protected]>
…ble-decoding (openclaw#96348) * fix(duckduckgo): decode & last in decodeHtmlEntities to avoid double-decoding decodeHtmlEntities decoded & FIRST, so result text that literally contains an entity (e.g. a page title 'How to escape < in HTML', which DuckDuckGo returns double-encoded as '&lt;') was re-decoded into markup: '&lt;' became '<' instead of the literal '<', corrupting the titles, snippets, and URLs the web-search tool returns to the model. Reorder so & is decoded last, matching the established convention elsewhere in the codebase (msteams/inbound.ts, openai-transport-stream.ts, launchd-plist.ts, doctor-session-snapshots.ts all decode & last). Behavior-preserving for all singly-encoded input. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * fix(duckduckgo): decode html entities in one pass --------- Co-authored-by: ly-wang19 <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> Co-authored-by: Vincent Koc <[email protected]>
What Problem This Solves
decodeHtmlEntitiesinextensions/duckduckgo/src/ddg-client.tsdecodes&first when un-escaping DuckDuckGo result HTML. When result text literally contains an HTML entity — e.g. a page titledHow to escape < in HTML— DuckDuckGo returns it double-encoded as&lt;. Decoding&first un-escapes it to<, which a later pass then re-decodes into a real<, corrupting the text:decodeHtmlEntitiesruns on every result'stitle,url, andsnippet(ddg-client.ts:104-106), which feedrunDuckDuckGoSearch— the execute path of the DuckDuckGo web-search tool (ddg-search-provider.ts). So the corrupted text becomes tool output the model consumes and may surface to the user.Fix
Decode
&last, matching the established convention everywhere else in this codebase —extensions/msteams/src/inbound.ts,src/agents/openai-transport-stream.ts,src/daemon/launchd-plist.ts, andsrc/commands/doctor-session-snapshots.tsall decode&last (msteams/inbound.ts even documents "must be last to prevent double-decoding"). The DDG decoder was the lone outlier. Behavior-preserving for all singly-encoded input.Evidence
Added a regression test (
does not double-decode escaped entities) inextensions/duckduckgo/src/ddg-search-provider.test.ts, and verified red → green by executing the exactdecodeHtmlEntitieschain against the bug cases and the existing test:The reorder only affects the buggy double-decode path; every singly-encoded input (everything the existing tests exercise) is unchanged.