Skip to content

fix(site): harden documentation rendering - #370

Draft
vincentkoc wants to merge 1 commit into
mainfrom
fix/codeql-docs-toc-sanitization-20260825
Draft

fix(site): harden documentation rendering#370
vincentkoc wants to merge 1 commit into
mainfrom
fix/codeql-docs-toc-sanitization-20260825

Conversation

@vincentkoc

Copy link
Copy Markdown
Member

Summary

  • stop deriving table-of-contents labels by regex-stripping rendered HTML
  • carry parser-owned heading facts into TOC rendering and escape labels at the output boundary
  • preserve current generated site output while covering nested markup and crafted tag fragments

Root cause

The docs renderer reparsed generated heading HTML with a multi-character regex replacement. Crafted tag fragments could survive that incomplete sanitization. The renderer now records structured heading labels during inline parsing and builds the TOC from those facts instead of reparsing HTML.

Verification

  • node --test scripts/*.test.mjs
  • node scripts/build-docs-site.mjs
  • generated dist/docs-site is byte-equivalent to base 97e14efdf91a7c9de1b68845321eb6355943b5f5
  • go vet ./...
  • go test ./...
  • go test -tags sqlite_fts5 ./...
  • Windows lock cross-compile
  • CGO-required negative build check
  • tagged SQLite FTS5 build
  • git diff --check

CodeQL alert: https://github.com/openclaw/wacli/security/code-scanning/2

@clawsweeper

clawsweeper Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

Comment thread scripts/docs-site-render.test.mjs Fixed
@vincentkoc
vincentkoc force-pushed the fix/codeql-docs-toc-sanitization-20260825 branch from 738cd4a to 72ac652 Compare August 25, 2026 19:15
@vincentkoc

Copy link
Copy Markdown
Member Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Aug 25, 2026
@clawsweeper

clawsweeper Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed August 25, 2026, 5:23 PM ET / 21:23 UTC.

ClawSweeper review

What this changes

The PR replaces HTML-based table-of-contents extraction with parser-owned heading data and escapes labels when rendering the static documentation site.

Merge readiness

Ready for maintainer review

Keep open for normal maintainer review. This member-authored draft is a focused, tested security hardening change and must not be auto-closed.

Priority: P2
Reviewed head: 72ac652a522795159522d018336c2ed62da6dcdd

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) The focused implementation, passing renderer test, and regression coverage make this a good normal-review candidate.
Proof confidence 🌊 off-meta tidepool Not applicable: The PR author is a repository member, so the external-contributor real-behavior-proof gate does not apply.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: The PR author is a repository member, so the external-contributor real-behavior-proof gate does not apply.
Evidence reviewed 5 items Structured rendering boundary: The renderer records H2/H3 heading labels from inline parsing, and the TOC escapes those labels when emitting links, avoiding the former rendered-HTML reparsing path.
Builder integration: The site generator consumes the renderer’s HTML and heading facts together, then passes headings to the new TOC renderer.
Focused regression coverage: The test covers nested formatting, blockquote headings, duplicate slugs, and crafted nested tag fragments, asserting escaped TOC output.
Findings None None.
Security None None.

Live Verification

Command: node scripts/build-docs-site.mjs

Result: PASS (completed)

built docs site: dist/docs-site
built docs site: dist/docs-site

Assertions:

  • PASS expect_output: built docs site: dist/docs-site

How this fits together

The docs-site builder reads Markdown, renders page HTML and heading metadata, then uses both to produce static documentation pages. The heading metadata now feeds the table of contents directly instead of being recovered from serialized HTML.

flowchart LR
  A[Markdown documents] --> B[Markdown renderer]
  B --> C[Heading facts]
  B --> D[Page HTML]
  C --> E[TOC renderer]
  E --> F[Escaped TOC links]
  D --> G[Static docs site]
  F --> G
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Code and test delta production +38, tests +51 The added parsing boundary is paired with more regression coverage than production growth.

Technical review

Best possible solution:

Land the parser-owned heading-data approach after normal maintainer approval, preserving the focused regression tests as the contract for safe TOC rendering.

Do we have a high-confidence way to reproduce the issue?

Yes: the focused renderer test runs crafted heading input through the PR’s parser and verifies the resulting TOC escapes tag fragments.

Is this the best way to solve the issue?

Yes: retaining structured heading facts before HTML serialization is a narrower and more maintainable boundary than sanitizing reparsed rendered HTML.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 97e14efdf91a.

Labels

Label changes:

  • add P2: This is a bounded static-documentation security hardening change with limited runtime blast radius.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The PR author is a repository member, so the external-contributor real-behavior-proof gate does not apply.

Label justifications:

  • P2: This is a bounded static-documentation security hardening change with limited runtime blast radius.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The PR author is a repository member, so the external-contributor real-behavior-proof gate does not apply.

Evidence

What I checked:

  • Structured rendering boundary: The renderer records H2/H3 heading labels from inline parsing, and the TOC escapes those labels when emitting links, avoiding the former rendered-HTML reparsing path. (scripts/docs-site-render.mjs:85, 72ac652a5227)
  • Builder integration: The site generator consumes the renderer’s HTML and heading facts together, then passes headings to the new TOC renderer. (scripts/build-docs-site.mjs:64, 72ac652a5227)
  • Focused regression coverage: The test covers nested formatting, blockquote headings, duplicate slugs, and crafted nested tag fragments, asserting escaped TOC output. (scripts/docs-site-render.test.mjs:28, 72ac652a5227)
  • Feature history: The docs-site deployment and adjacent renderer path originate with the hosted-docs work by Peter Steinberger; current-base blame also assigns the renderer’s surrounding implementation to that history. (scripts/docs-site-render.mjs:6, 9fff67cd3bec)
  • Release boundary: The current release tag v0.17.1 contains the base commit, while the PR head is not tagged; this change is not already shipped on main. (scripts/docs-site-render.mjs:137, 97e14efdf91a)

Likely related people:

  • Peter Steinberger: Introduced the docs-site deployment and has the strongest adjacent history on the static documentation renderer. (role: original docs-site contributor; confidence: high; commits: 9fff67cd3bec, bbeaebf3a15a; files: scripts/build-docs-site.mjs, scripts/docs-site-render.mjs)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

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

Labels

P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants