feat: escape raw HTML in stranger doc comments (torb doc --escape-html) #481

Merged
argus merged 3 commits from loop/234-safe-html into main 2026-10-25 13:13:57 +00:00
Collaborator

Closes #234

Summary

  • std/markdown: MarkdownDocument.safeHtml() beside html(). Raw HTML blocks and inline spans are written as escaped text; a link or image destination with the scheme javascript:, vbscript: or data: (case-insensitive, after trimming and removing control characters and whitespace) becomes an empty href/src. html() is unchanged.
  • torb doc --escape-html threads that choice through markdownHtml and the site generator; without the flag the output is what it was. Parsed, listed in the usage text and documented in docs/tooling/torb-doc.md (synopsis, flag list, a paragraph under "The site"); skills/ copies edited by hand to match the generated form.
  • The registry documentation worker passes --escape-html to torb doc --output. A toolchain that does not know the flag refuses the command, so the version is failed (fails closed); RELEASE.md section 7.7 and the registry README name both.

Seed: not touched (no syntax, native, build-used driver flag or looked-up std name; the compiler's own build never passes the flag).

Acceptance criteria

  • std/markdown tests, group "safe HTML": hostile blocks and spans as escaped text, script-scheme destinations empty, ordinary destinations unchanged. CommonMark examples run through html() as before. Status: written, awaiting CI.
  • compiler/tests/reference.test.trb: a doc comment with a raw HTML block and span renders as text with --escape-html, as HTML without it. Status: written, awaiting CI.
  • Flag parsed, in usage text, in docs/tooling/torb-doc.md; docs/standard-library/markdown.md documents safeHtml. The skills/ copies were edited by hand (no torb on the worker), CI's docs skill --check is the proof.
  • Registry worker passes --escape-html; RELEASE.md 7.7 names the flag and the fail-closed behaviour. The registry test has no argument-list assertion, so it now checks the stored page instead: a <script> in a doc comment is written as &lt;script&gt;.
  • sh tools/gates.sh a green in forge CI: pending, nothing was run locally (CI only).

Test

Not run locally (no bootstrap/gates on the worker); tools/check-commits.sh origin/main HEAD is clean. Forge CI is the first run, so format or typo rounds are possible.

Closes #234 ## Summary - `std/markdown`: `MarkdownDocument.safeHtml()` beside `html()`. Raw HTML blocks and inline spans are written as escaped text; a link or image destination with the scheme `javascript:`, `vbscript:` or `data:` (case-insensitive, after trimming and removing control characters and whitespace) becomes an empty `href`/`src`. `html()` is unchanged. - `torb doc --escape-html` threads that choice through `markdownHtml` and the site generator; without the flag the output is what it was. Parsed, listed in the usage text and documented in `docs/tooling/torb-doc.md` (synopsis, flag list, a paragraph under "The site"); `skills/` copies edited by hand to match the generated form. - The registry documentation worker passes `--escape-html` to `torb doc --output`. A toolchain that does not know the flag refuses the command, so the version is `failed` (fails closed); RELEASE.md section 7.7 and the registry README name both. Seed: not touched (no syntax, native, build-used driver flag or looked-up std name; the compiler's own build never passes the flag). ## Acceptance criteria - [x] `std/markdown` tests, group "safe HTML": hostile blocks and spans as escaped text, script-scheme destinations empty, ordinary destinations unchanged. CommonMark examples run through `html()` as before. Status: written, awaiting CI. - [x] `compiler/tests/reference.test.trb`: a doc comment with a raw HTML block and span renders as text with `--escape-html`, as HTML without it. Status: written, awaiting CI. - [x] Flag parsed, in usage text, in `docs/tooling/torb-doc.md`; `docs/standard-library/markdown.md` documents `safeHtml`. The `skills/` copies were edited by hand (no `torb` on the worker), CI's `docs skill --check` is the proof. - [x] Registry worker passes `--escape-html`; RELEASE.md 7.7 names the flag and the fail-closed behaviour. The registry test has no argument-list assertion, so it now checks the stored page instead: a `<script>` in a doc comment is written as `&lt;script&gt;`. - [ ] `sh tools/gates.sh a` green in forge CI: pending, nothing was run locally (CI only). ## Test Not run locally (no bootstrap/gates on the worker); `tools/check-commits.sh origin/main HEAD` is clean. Forge CI is the first run, so format or typo rounds are possible.
A second HTML step beside html(): raw HTML blocks and spans are written as escaped text, and a link or image
destination that starts with javascript:, vbscript: or data: is written empty. html() is unchanged.

Refs #234
feat(doc): --escape-html for stranger's doc comments, passed by the registry worker
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Failing after 10s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 2m26s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 13m4s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Failing after 30s
ci / every host emits the same C (pull_request) Successful in 4m55s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m14s
ci / gates (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / tier A (linux-x64) (pull_request) Has been cancelled
3507d5672d
torb doc --escape-html writes the raw HTML of the doc comments as text and a link to a script as an empty one.

Refs #234
orion requested review from argus 2026-10-25 07:25:55 +00:00
orion force-pushed loop/234-safe-html from 3507d5672d
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Failing after 10s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 2m26s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 13m4s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Failing after 30s
ci / every host emits the same C (pull_request) Successful in 4m55s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m14s
ci / gates (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / tier A (linux-x64) (pull_request) Has been cancelled
to ce73eaf355
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 11s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 7m24s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 13m34s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m31s
ci / every host emits the same C (pull_request) Successful in 4m46s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m20s
ci / tier A (linux-x64) (pull_request) Failing after 24m57s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Failing after 0s
2026-10-25 08:56:03 +00:00
Compare
argus requested changes 2026-10-25 12:00:54 +00:00
Dismissed
argus left a comment

Review of ce73eaf (round 1). The approach is sound: escaping is applied at the single renderer choke point (HtmlRenderer.safe), html() and the default of torb doc stay unchanged, the registry fails closed on an older toolchain, scope matches #234, and the tests cover blocks, spans, scheme case/whitespace variants, unchanged destinations and the stored registry page. Two things to fix:

  1. [blocker] CI red on ce73eaf: ci / tier A (linux-x64) fails in exactly one gate, format --check ("2 of 1483 files would change"): compiler/tests/reference.test.trb and std/markdown/src/html.trb. All other gates (docs skill/site check, compiler tests, std tests native+VM, tier B, registry, pdisc) are green. Run torb format on those two files and push; ci / gates is red only because of this.

  2. [blocker] Documentation contradicts the behavior for data: images. docs/tooling/torb-doc.md (and its skills/torbscript-projects/... copy) says the flag blanks "data: other than an image". The implementation (hasScriptScheme via HtmlRenderer.uri) blanks every data: destination, images included, and your own test safe("![a](data:text/html,x)") == ...src=\"\"... asserts that. Safer behavior is fine, but the doc must say so: drop "other than an image" in both copies (the markdown.md wording is already correct). The docs skill --check stays green only if both copies are edited identically.

Non-blocking: none. Re-review will check only these two points and the lines changed since.

Review of ce73eaf (round 1). The approach is sound: escaping is applied at the single renderer choke point (`HtmlRenderer.safe`), `html()` and the default of `torb doc` stay unchanged, the registry fails closed on an older toolchain, scope matches #234, and the tests cover blocks, spans, scheme case/whitespace variants, unchanged destinations and the stored registry page. Two things to fix: 1. [blocker] CI red on ce73eaf: `ci / tier A (linux-x64)` fails in exactly one gate, `format --check` ("2 of 1483 files would change"): `compiler/tests/reference.test.trb` and `std/markdown/src/html.trb`. All other gates (docs skill/site check, compiler tests, std tests native+VM, tier B, registry, pdisc) are green. Run `torb format` on those two files and push; `ci / gates` is red only because of this. 2. [blocker] Documentation contradicts the behavior for `data:` images. `docs/tooling/torb-doc.md` (and its `skills/torbscript-projects/...` copy) says the flag blanks "`data:` other than an image". The implementation (`hasScriptScheme` via `HtmlRenderer.uri`) blanks every `data:` destination, images included, and your own test `safe("![a](data:text/html,x)") == ...src=\"\"...` asserts that. Safer behavior is fine, but the doc must say so: drop "other than an image" in both copies (the `markdown.md` wording is already correct). The `docs skill --check` stays green only if both copies are edited identically. Non-blocking: none. Re-review will check only these two points and the lines changed since.
orion force-pushed loop/234-safe-html from ce73eaf355
Some checks failed
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 11s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 7m24s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 13m34s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m31s
ci / every host emits the same C (pull_request) Successful in 4m46s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m20s
ci / tier A (linux-x64) (pull_request) Failing after 24m57s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Failing after 0s
to cbe8448a3d
Some checks failed
ci / commit messages (pull_request) Has been cancelled
ci / what the change touches (pull_request) Has been cancelled
ci / gates (pull_request) Has been cancelled
pdisc / pdisc (pull_request) Has been cancelled
2026-10-25 12:02:49 +00:00
Compare
orion force-pushed loop/234-safe-html from cbe8448a3d
Some checks failed
ci / commit messages (pull_request) Has been cancelled
ci / what the change touches (pull_request) Has been cancelled
ci / gates (pull_request) Has been cancelled
pdisc / pdisc (pull_request) Has been cancelled
to aef67bcae7
Some checks failed
ci / commit messages (pull_request) Has been cancelled
ci / what the change touches (pull_request) Has been cancelled
ci / gates (pull_request) Has been cancelled
pdisc / pdisc (pull_request) Has been cancelled
2026-10-25 12:02:54 +00:00
Compare
orion force-pushed loop/234-safe-html from aef67bcae7
Some checks failed
ci / commit messages (pull_request) Has been cancelled
ci / what the change touches (pull_request) Has been cancelled
ci / gates (pull_request) Has been cancelled
pdisc / pdisc (pull_request) Has been cancelled
to 4bfb26e756
All checks were successful
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 10s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 7m22s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier B (linux-x64) (pull_request) Successful in 13m31s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m28s
ci / every host emits the same C (pull_request) Successful in 4m54s
ci / tier A (linux-x64) (pull_request) Successful in 24m17s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m10s
ci / gates (pull_request) Successful in 0s
2026-10-25 12:03:11 +00:00
Compare
Author
Collaborator

Addressed review 430 in 4bfb26e (rebased onto main f630c25):

  1. torb format run on compiler/tests/reference.test.trb and std/markdown/src/html.trb; torb format --check is clean on all 9 changed .trb files.
  2. docs/tooling/torb-doc.md and its skills/ copy now read "data:, images included" (edited identically, matches markdown.md and the implementation).

pdisc check is ok. Nothing else changed.

Addressed review 430 in 4bfb26e (rebased onto main f630c25): 1. `torb format` run on `compiler/tests/reference.test.trb` and `std/markdown/src/html.trb`; `torb format --check` is clean on all 9 changed `.trb` files. 2. `docs/tooling/torb-doc.md` and its `skills/` copy now read "`data:`, images included" (edited identically, matches `markdown.md` and the implementation). `pdisc check` is ok. Nothing else changed.
orion requested review from argus 2026-10-25 12:03:15 +00:00
argus approved these changes 2026-10-25 13:13:55 +00:00
argus left a comment

Re-review of 4bfb26e (round 2). Earlier findings:

  1. CI red (format): fixed. ci / gates and ci / tier A (linux-x64) are green on this head, as are tier B, registry, pdisc and the playground.
  2. data: doc contradiction: fixed. docs/tooling/torb-doc.md and its skills/ copy now read "data:, images included", edited identically, matching markdown.md and the implementation/test.

Checklist: tests ok (std/markdown safe-HTML group, reference test, registry stored-page check); correctness ok (escaping at the single renderer choke point, html() and the default of torb doc unchanged, registry fails closed on an older toolchain); scope = #234; no secrets or new services; no data/format change; docs updated; no new boundary.

Non-blocking: none.

Re-review of 4bfb26e (round 2). Earlier findings: 1. CI red (format): fixed. `ci / gates` and `ci / tier A (linux-x64)` are green on this head, as are tier B, registry, pdisc and the playground. 2. `data:` doc contradiction: fixed. `docs/tooling/torb-doc.md` and its `skills/` copy now read "`data:`, images included", edited identically, matching `markdown.md` and the implementation/test. Checklist: tests ok (std/markdown safe-HTML group, reference test, registry stored-page check); correctness ok (escaping at the single renderer choke point, `html()` and the default of `torb doc` unchanged, registry fails closed on an older toolchain); scope = #234; no secrets or new services; no data/format change; docs updated; no new boundary. Non-blocking: none.
argus merged commit 3afd3ce694 into main 2026-10-25 13:13:57 +00:00
argus deleted branch loop/234-safe-html 2026-10-25 13:13:57 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!481
No description provided.