Repository navigation
Harden local mode against script injection and cross-origin file reads - #68
Merged
Merged
Conversation
Raw HTML was passed through (goldmark WithUnsafe), so scripts in a rendered document ran on the proxy origin and could fetch /local/ files. Add markdown.Render (convert, rewrite links, sanitize) and use it in all handlers. Tables, images, details, highlighting, line anchors and inline SVG are preserved. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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.
Problem
In local mode
/local/<absolute path>serves any readable file without authentication. Two paths let untrusted content reach it from the user's browser:WithUnsafe) was passed through, so a<script>in e.g. a remote README ran on the proxy origin and couldfetch('/local/...')..html/.svgran script on the proxy origin too.Changes
markdown.Render= convert → rewrite links → sanitize). Tables, images,<details>, highlighting, line anchors, math and inline SVG are preserved; scripts, iframes,on*,javascript:and SVGscript/foreignObject/useare removed.localhost,127.0.0.1,[::1].corsrequests and mismatchedOrigin(local mode). No CORS headers are sent.script-src 'nonce-…',connect-src 'self',frame-ancestors 'none', …). Inline event handlers andjavascript:links in templates were replaced withaddEventListener.nosniff, plusContent-Security-Policy: sandbox allow-scriptsfor HTML/SVG/XML so they run in an opaque origin.Authorizationis not forwarded on cross-host redirects./local/is intentionally not restricted (viewing logs under e.g.~/.claude/is a primary use case); the above blocks the routes to it instead.Behavior changes
.htmlfiles are sandboxed (scripts run, but nolocalStorage/cookies).<style>tags andstyleattributes other than width/height in Markdown are removed.Testing
go test ./...andmake buildpass (new tests for sanitizing, Host/Origin, CSP, passthrough, SRI, redirect credentials).🤖 Generated with Claude Code