fix(seo): escape JSON-LD script content to prevent breakout - #208
Conversation
|
@SebTardif is attempting to deploy a commit to the Jamie's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 8:02 PM ET / July 12, 2026, 00:02 UTC. Summary Reproducibility: yes. Current main directly inserts JSON.stringify output into an HTML raw-text script element, so structured data containing a literal closing-script sequence gives a deterministic source-level reproduction; the supplied browser proof confirms the corrected path. Review metrics: 3 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Next step before merge
Security Review detailsBest possible solution: Merge the exact head after ordinary maintainer approval, retaining centralized post-serialization escaping at the sole JSON-LD sink and both unit and generated-output regression layers. Do we have a high-confidence way to reproduce the issue? Yes. Current main directly inserts JSON.stringify output into an HTML raw-text script element, so structured data containing a literal closing-script sequence gives a deterministic source-level reproduction; the supplied browser proof confirms the corrected path. Is this the best way to solve the issue? Yes. Escaping literal less-than characters after JSON serialization at the shared sink is the narrowest maintainable solution because it preserves parsed values, removes every HTML tag opener, and covers all current structured-data callers. AGENTS.md: found, but no applicable review policy affected this item. Codex review notes: model internal, reasoning high; reviewed against a6f92f38a2b0. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
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. How this review workflow works
Review history (8 earlier review cycles)
|
|
@clawsweeper re-review Added What Problem This Solves, Evidence, and Real behavior proof with node escape demo (raw </script> removed, JSON roundtrip preserved). |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Fixed the no-op escape: source is now |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
296a742 to
c3a15ed
Compare
|
Maintainer proof for final exact head
Risk: low after proof. Files: 4, +72/-1. Sebastien remains credited as PR author and commit co-author. Merge recommendation: supported. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Final exact-head proof is in the updated maintainer comment above; the changelog finding is fixed. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
What Problem This Solves
Layout.astroembeds structured data withset:html={JSON.stringify(item)}. If any string field contains a raw</script>sequence, the HTML parser closes the ld+json script elementearly (classic JSON-in-script breakout).
Evidence
Fixed escape uses a literal
\u003csequence in the serialized JSON(not a JS string that is already
<).contains_raw_close: falsemeans the HTML stream has no raw</script>inside the JSON text.
JSON.parsestill restores the original name.Summary
<as the six-character sequence\u003cafterJSON.stringify"\\u003c"(a prior"\u003c"form was a no-op)Real behavior proof
astro buildHTML on this machine (design-system package resolution blocked in worktree); logic matches the committed Layout expressionRelated
"\u003c"form