From cf3547cd1a6f1d1fec45e3648e3b9e040a8ac803 Mon Sep 17 00:00:00 2001 From: Merlin Date: Sun, 11 Oct 2026 06:50:32 +0000 Subject: [PATCH] Q29 DONE: render-site-guards.md - the guards that are not the walk (22 fixtures + control, second guarantee stated, one finding: unguarded int(sats) leaves a partial tree) --- WORK-QUEUE.md | 13 ++ checkins/2026-10-11-merlin.md | 111 +++++++++++++++++ recoveries/render-site-guards.md | 199 +++++++++++++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 recoveries/render-site-guards.md diff --git a/WORK-QUEUE.md b/WORK-QUEUE.md index 4955c3d..440197b 100644 --- a/WORK-QUEUE.md +++ b/WORK-QUEUE.md @@ -3576,3 +3576,16 @@ numbers below are re-derived from that file plus `Q28-RESULTS.json`. the builder SHA in the results file is `c4127c6c…` — the same builder the publish precondition names. The count is the one number in Q28 that cannot be rebuilt from the raw evidence; the property it was meant to state is proven by the fixtures themselves. + +**Status: DONE 2026-10-11 — `recoveries/render-site-guards.md` (Merlin), scratch tree `/root/crucible/q29/`. 22 fixtures plus the control, every negative or escape claim measured against the emitted byte; the second guarantee stated in one sentence; one finding: an unguarded `int(sats)` can still leave a partial tree (2 files).** +- **The second guarantee, restated as one sentence:** every string the build emits is either escaped for its context or derived from a value that cannot carry a metacharacter — `esc()` (`html.escape(v, quote=True)`) for HTML text and attributes, `json.dumps` plus the ``, `meta description`, `h1`, index label all escaped; JSON-LD headline raw `` with escaped `<\/b>`); `` in title, uppercase ``, and `` (payload `<\/script>`; raw `` in date (`datePublished` escaped, Date line escaped); metacharacters in `contributor.display_name` (byline escaped, `author.name` raw ``, safe in payload context); `" onmouseover=…` and `` in `contributor.handle` (href `"`, JSON-LD `\"` and `<\/script>`); `` in `plain_summary.text`; `` (payload `<\/script>`, raw `` in `date`; metacharacters in `contributor.display_name` +(byline escaped, `author.name` raw ``); `" onmouseover=…` and `` in +`contributor.handle` (href `"`, JSON-LD `\"` / `<\/script>`); `` in +`plain_summary.text`; `'` | 0 | 125 | `"headline": " …"`; raw ` & '` | 0 | 125 | panel `<!-- [archivist note] --> & <b>` | +| 13 | `excerpt-metachars` | `excerpts[0].text = 'they said "5 < 6" & it\'s true'` | 0 | 125 | blockquote `they said "5 < 6" & it's true` | +| 14 | `excerpt-url-quote` | `excerpts[0].url = 'https://x.com/a" onmouseover=alert(1)'` | 0 | 125 | `` (no `safe_url` on excerpt URLs; `esc()` still holds the attribute) | +| 15 | `sourceurl-quote` | `block-6.body_source_url = 'https://x.com/a" onmouseover=alert(1)'` | 0 | 125 | `Source: …` | +| 16 | `quotebranch-body` | `block-6.body = 'he said "hi" and 5 < 6'` (quote branch) | 0 | 125 | blockquote `he said "hi" <b> and 5 < 6` | +| 17 | `reuse-status` | `block-5.receipt.reuse_status = 'yes'` | 0 | 125 | `Image reuse: <i>yes</i>.` | +| 18 | `receipt-usd-nonnumeric` | `block-5.receipt.usd = '7'` | 0 | 125 | `Amount $<b>7`; `Arithmetic not checked`; `Amount in sats 22,765` (the surviving int) | +| 19 | `receipt-sats-nonnumeric` | `block-5.receipt.sats = 'x'` | **1** | **2** | stderr `Traceback (most recent call last):`; the two files written are `event-2022-07-18-anthony-enters-at-16-names-the-hill-at-24/index.html` and `event-2022-07-18-the-5-invitation-becomes-a-chain/index.html` — **a partial tree** (see §5) | +| 20 | `status-metachar` | `magazine-001.status = ''` | 1 | 0 | `BUILD FAILED: block[30] unknown status ''` — validation, not escaping | +| 21 | `year-derived` | `magazine-001.sort_date = '2023-08-27'` | 0 | 125 | index year headings end `('<b>2', '<b>2')`; `li id="magazine-001"` unchanged | +| 22 | `control` | no mutation | 0 | 125 | tree digest `91ecf6bf939a2a499983066a2331bb953eab8a4ca85c66a8a19f42cb1b28f7a8` — **byte-identical to the Q26 baseline and to the live `site-ledger`** (`diff -rq` silent) | + +**Proof-or-falsify results, stated against the emitted byte, not the intent:** + +- `` in `title`, `date`, `display_name`, `plain_summary.text`: **proven safe in all four.** + Payload landings carry `<\/script…`; HTML landings carry `</script>`. Raw `alert(1)<\/script>-->"`), and is + inert there: a script element is a raw-text element, so `