Skip to content

fix(explorer): escape HTML before injecting raw JSON into the DOM - #496

Open
memosr wants to merge 1 commit into
canopy-network:developmentfrom
memosr:fix/escape-raw-json-html
Open

fix(explorer): escape HTML before injecting raw JSON into the DOM#496
memosr wants to merge 1 commit into
canopy-network:developmentfrom
memosr:fix/escape-raw-json-html

Conversation

@memosr

@memosr memosr commented Aug 4, 2026

Copy link
Copy Markdown

Summary

The transaction, block and order Raw views serialize an object with
JSON.stringify, split the result into lines, and hand each line to
dangerouslySetInnerHTML. JSON.stringify does not escape &, < or >, so any
string field in the serialized object reaches the DOM as markup rather than as text.

Several of these fields are chain-supplied rather than controlled by the person viewing
the page. transaction.memo in particular is free-form and only length-limited
(200 bytes, lib/tx.go), with no content validation.

Changes

  • src/lib/utils.ts - added escapeHtml.
  • src/components/transaction/TransactionDetailPage.tsx
  • src/components/block/BlockDetailInfo.tsx
  • src/components/token-swaps/OrderDetailPage.tsx

Each raw view now escapes the serialized JSON before the syntax-highlight step.
Ordering matters: escaping first leaves the highlighter's own <span> tags, which are
inserted afterwards, intact. Quotes are deliberately not escaped, because the highlight
patterns match on ".

Verification

Running { height: 12, memo: '<b>markup</b> & "quoted"', ok: true } through the
transaction view's highlight chain:

raw <b> reaches output key / value / number / bool highlighting
before yes yes
after no yes

tsc --noEmit passes. eslint reports no new findings; the two prefer-const errors it
reports in utils.ts are pre-existing and untouched by this change.

Notes

CnpyColorIcon.tsx also uses dangerouslySetInnerHTML, but its input is a locally
generated SVG string rather than API data, so it is left alone.

The transaction, block and order "Raw" views serialize an object with
JSON.stringify and pass each resulting line to dangerouslySetInnerHTML.
JSON.stringify does not escape &, < or >, so string fields in the
serialized object were rendered as markup instead of as text.

Escape the serialized JSON before the syntax-highlight step, so the
highlighter's own span tags are unaffected. Quotes are deliberately left
unescaped because the highlight patterns match on them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant