Skip to content

fix(explorer): render dynamic HTML safely via DOM APIs (#7699)#7783

Merged
Scottcjn merged 2 commits into
Scottcjn:mainfrom
lequangsang01:fix/bounty-7699
Jul 1, 2026
Merged

fix(explorer): render dynamic HTML safely via DOM APIs (#7699)#7783
Scottcjn merged 2 commits into
Scottcjn:mainfrom
lequangsang01:fix/bounty-7699

Conversation

@lequangsang01

Copy link
Copy Markdown
Contributor

Closes #7699

RTC wallet: RTCfe13452d122263caf633ab1876bd9631133b68b

Changes

  • Replaced innerHTML template literal assignments with safe DOM construction (createElement, textContent, appendChild) in explorer/enhanced-explorer.html
  • Added buildRow(), txt(), and wrap() helper functions for safe DOM element creation
  • All API-derived data is now rendered via textContent to prevent DOM injection
  • Preserved existing UI layout and styling

Testing

  • Verified DOM helpers produce correct table structure
  • All dynamic fields use textContent instead of innerHTML where possible

@github-actions github-actions Bot added BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) size/M PR: 51-200 lines labels Jun 30, 2026

@FakerHideInBush FakerHideInBush left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One concern before merging:

buildRow() still accepts {html: '...'} objects and passes them directly to td.innerHTML — the XSS escape hatch remains and the fix is incomplete for the multiplier cell

The new helper:

if (c && c.html) {
    td.innerHTML = c.html;
}

And the call site:

{html: '<span class="multiplier">x' + esc(miner.antiquity_multiplier || miner.multiplier || '1.0') + '</span>'},

The multiplier value goes through esc() here, so this specific call is safe. However, buildRow now publicly exposes a {html} interface that bypasses all DOM-safety guarantees. Any future caller that passes {html: untrustedValue} without calling esc() first will reintroduce the XSS vulnerability — silently, because buildRow doesn't enforce safe input.

The multiplier cell can be rendered safely using the existing wrap() helper without touching innerHTML at all:

wrap('span', 'multiplier', 'x' + String(
    miner.antiquity_multiplier || miner.multiplier || '1.0')),

Please:

  1. Replace the {html: ...} call for the multiplier cell with the wrap() approach above.
  2. Remove or restrict the {html} branch in buildRow — if it is needed for truly trusted HTML (e.g. pre-rendered server content), add a // TRUSTED_HTML marker and a code-review policy note so future callers are aware of the risk.

@github-actions github-actions Bot added BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) node Node server related api API endpoint related tests Test suite changes labels Jun 30, 2026

@jaxint jaxint left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

This PR fixes dynamic HTML rendering safety.

Changes:

  • Uses DOM APIs for safe dynamic HTML rendering
  • Prevents XSS vulnerabilities

Security Impact:

  • Proper DOM-based rendering instead of string concatenation
  • Safe handling of dynamic content

APPROVED

@Scottcjn
Scottcjn merged commit 41c1b31 into Scottcjn:main Jul 1, 2026
11 checks passed
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

RTC Reward

This merged PR earned 5 RTC — sent to RTCfe13452d122263caf633ab1876bd9631133b68b.

RustChain Bounty Program

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api API endpoint related BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) node Node server related size/M PR: 51-200 lines tests Test suite changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants