security: block URI scheme bypasses + tree-sitter grammar v1.0 parity (v1.0.1)#19
Merged
rjmitchell merged 17 commits intomainfrom Apr 10, 2026
Merged
security: block URI scheme bypasses + tree-sitter grammar v1.0 parity (v1.0.1)#19rjmitchell merged 17 commits intomainfrom
rjmitchell merged 17 commits intomainfrom
Conversation
Specs: - JS renderer parity (completed this session) - Include-aware watch (completed this session) - Landing page redesign (completed this session) - Editor v1.0 parity: tree-sitter grammar upgrade, nested lists, comments, converter/serializer updates (ready for implementation) Plans: - JS renderer parity (completed) - Include-aware watch (completed) - Landing page redesign (completed) - Editor v1.0 parity (ready for next session, includes CSO security fix for javascript: URI XSS in renderers)
…ns and case-insensitive case
…for editor v1.0 parity - Strip trailing whitespace from comment node text in block-converter (round-trip fix) - Add 3 unit tests for comment conversion (trailing newline, indented prefix, no newline) - Update CLAUDE.md test counts: 357 Python / 331 editor / 123 JS - Add Editor v1.0 parity entry to TODOS.md Completed section
…ulti-paragraph ordered corpus
…eserialize guards
Block //evil.com (protocol-relative) URLs which browsers treat as absolute, and decode percent-encoding before scheme extraction to catch javascript%3a... bypasses. Both Python and JS renderers updated; regression tests added.
Add guard at the top of scan_indent_tokens that detects the error-recovery state (all 5 external symbols valid simultaneously) and returns false immediately to prevent incorrect state mutation during recovery.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ships v1.0.1 with two main things plus a pile of hardening.
Security (CSO audit findings #10, #11 + adversarial review):
javascript:anddata:URI schemes in linkhrefand figuresrcvia allowlist (http,https,mailto,tel), defaulting to#. Both Python and JS renderers.//evil.com) — browsers treat these as absolute, so[text -> //evil.com]was a valid CLN document that slipped past the sanitizer as an open redirect.javascript%3a...,JAVASCRIPT%3A...) — browsers decode before routing, so literal-colon detection was bypassable. Both renderers now percent-decode before scheme extraction and handle malformed sequences safely.Tree-sitter grammar v1.0 parity (closes the gap where the Python parser supported nested lists + multi-paragraph items but the grammar was still on v0.1):
scan_indent_tokensdistinguishes nested list markers (INDENT), multi-paragraph continuations (LIST_CONTINUATION requiresafter_blank_line+ indent > 0), and dedents (zero-width DEDENT). Bails during tree-sitter error recovery to avoid corrupting the indent stack.list_item_body,list_item_continuation,nested_list. Both unordered and ordered nesting work, including mixed nesting.Editor internals (to consume the new CST shape):
clnCommentblock type for// commentlines.children[]fromlist_item_body— sharedconvertListItemBodyhelper between unordered and ordered.10.).Hardening / refactors:
TREE_SITTER_SERIALIZATION_BUFFER_SIZEinstead of magic1024, removes unused<string.h>include, collapses redundant deserialize guards.href="#"checks, case-insensitive scheme coverage, converter unit tests for nested list paths.Test Coverage
AI-assessed coverage: ~95% (above 80% target). All critical paths have ★★★ tests (behavior + edge cases + error paths). The one structural gap (scanner corrupt-buffer branches) is defensive C code with no direct test framework — acceptable.
Pre-Landing Review
Two stages of review ran:
Structural pass: CLEAN. Two informational items (both non-blocking, both tracked):
props.textwould round-trip incorrectly, but this can't happen from a parsed CLN source (grammar enforces single-line comments).Specialist review: 9 informational items found across testing + maintainability. All 7 mechanical items auto-fixed across 3 commits:
data:figure src test to JS, ordered list continuation converter test, multi-paragraph ordered corpus testconvertListItemBodyhelper (DRY, -30 lines)1024withTREE_SITTER_SERIALIZATION_BUFFER_SIZE<string.h>includeSkipped: 2 stylistic items (LIST_INDENT constant for a 2-char string, cross-language safeUrl reference comment).
Adversarial review: Found 2 CRITICAL bypasses in the new URL sanitizer (C-1 protocol-relative, C-2 percent-encoded). Both fixed in commit
2ad7306with regression tests in both renderers. Plus 1 INFORMATIONAL scanner hardening fix (error-recovery bail) in commit3969fbd.Plan Completion
All 39 checkboxes in
docs/superpowers/plans/2026-04-09-editor-v1-parity.mdmarked done. Every planned task delivered. Additional scope added during ship: adversarial-driven URL bypass fixes (C-1, C-2), scanner error-recovery guard, DRY refactors.Scope Drift
CLEAN. Intent: editor v1.0 parity + security fix. Delivered: exactly that, plus ship-time hardening driven by adversarial review.
TODOS
Completed: "Editor v1.0 parity + URL security (v1.0.1)" entry updated in TODOS.md with the full shipped scope.
Test plan
//evil.com→#)javascript%3aalert(1)→#)🤖 Generated with Claude Code