Skip to content

fix: check escaped backslashes on Windows - #2810

Merged
dunglas merged 1 commit into
mainfrom
fix/windows-escaped-backslash
Nov 5, 2026
Merged

dunglas merged 1 commit into
mainfrom
fix/windows-escaped-backslash

Conversation

@dunglas

@dunglas dunglas commented Nov 4, 2026

Copy link
Copy Markdown
Member

Security fix (Windows only). Follow-up to 393e007.

On Windows, Caddy path matchers whose pattern contains % read a backslash as %2f, which they do not resolve as a separator. Go escapes a backslash even when RawPath is empty, so escapedPathSelectsAnotherScript returned early for /public/tool.php%5C..%5C..%5Cadmin%5Ctool.php: a /public/%* rule matched it, but admin/tool.php ran.

The check now also runs when the path contains a backslash on Windows. Backslashes are folded into separators before comparing, which also fixes a regression: legitimate paths such as /dir\index.php were rejected with a 400.

Found while porting the fix to Caddy: caddyserver/caddy#8357

Assistance Disclosure

Claude Code (Claude Opus 5.5) found the issue while porting the fix to Caddy, and wrote the patch and tests. I reviewed and tested the result.

Caddy's path matchers whose pattern contains "%" read a backslash as
"%2f" on Windows, which they do not resolve as a separator. Go escapes
a backslash even when RawPath is empty, so the escaped-path check
skipped "/public/tool.php%5C..%5C..%5Cadmin%5Ctool.php": a
"/public/%*" rule matched it, but admin/tool.php ran.

The check now also runs when the path contains a backslash on Windows,
and folds backslashes into separators before comparing, so legitimate
paths such as "/dir\index.php" are no longer rejected with a 400.
@dunglas
dunglas merged commit 8acbfc6 into main Nov 5, 2026
44 of 45 checks passed
@dunglas
dunglas deleted the fix/windows-escaped-backslash branch November 5, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant