[security] Fix double-slash path blocking to return 400 in both Tornado and Starlette#13822
Conversation
✅ PR preview is ready!
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
Pull request overview
This PR fixes an E2E test to expect the correct HTTP status code (400 Bad Request) from the PathSecurityMiddleware instead of the previously expected 403 Forbidden.
Changes:
- Updated
test_double_slash_not_redirected_to_externalto expect status code 400 instead of 403 - Updated test comments to accurately reference PathSecurityMiddleware
464a7ac to
3302361
Compare
…lette The PathSecurityMiddleware in Starlette returns 400 Bad Request for double-slash paths. The Tornado server previously relied on Tornado's built-in handling which returned 403. Added UnsafePathBlockHandler to the Tornado server to explicitly block double-slash paths with 400, matching the Starlette behavior. Updated the E2E test accordingly.
3302361 to
4173795
Compare
|
## Summary
This PR aligns Tornado's handling of double-slash paths with the Starlette middleware by returning 400 for Code QualityThe new Test CoverageThe e2e test now asserts the 400 response for double-slash paths ( Backwards CompatibilityBehavior changes from 403 to 400 for Security & RiskThis is a security hardening change that blocks protocol-relative path patterns earlier in the request flow. No new security risks or regression hotspots identified. AccessibilityNo frontend/UI changes. Recommendations
VerdictAPPROVED: Low-risk security hardening with updated test coverage; only a minor docstring consistency note. This is an automated AI review using |
| # SECURITY: Block unsafe paths (double-slash, UNC paths, etc.) | ||
| # before any other handler. Matches PathSecurityMiddleware in Starlette. | ||
| (r"^//.*$", UnsafePathBlockHandler), |
There was a problem hiding this comment.
Can you double check with Claude / Cursor that there aren't unintended side-effects with blocking all //?
There was a problem hiding this comment.
No unintended side-effects. The // blocking is safe because:
-
All route construction goes through
make_url_path()which strips leading/trailing slashes from both
the base URL and path segments before joining. It's mathematically impossible for this function to produce a
//prefix — e.g.make_url_path("", "health")→"/health",make_url_path("/app/", "/health")→
"/app/health". -
server.baseUrlPathis normalized — even if a user sets it to"/"or"//", slashes are stripped
before route construction. -
The
RemoveSlashHandleralready has a negative lookahead(?!/)in its regex, explicitly preventing
matching paths starting with//. Before this PR those paths would 404; now they 400 with a clear message. -
WebSocket, static files, media, components, OAuth, upload endpoints — all constructed via
make_url_path_regex(), all safe. -
Starlette already has identical protection in
PathSecurityMiddleware. The Tornado
UnsafePathBlockHandlerjust brings parity. -
The codebase itself acknowledges this — there's a comment in
server.py: "if the path starts with a
double slash //, the redirect will point the browser to the wrong host" — confirming//paths were never
intended to be valid.
The only paths that start with // are malicious inputs (protocol-relative URL attacks like //evil.com).
No legitimate Streamlit functionality produces or requires them.

Summary
UnsafePathBlockHandlerto the Tornado server that blocks double-slash paths with400 Bad Request, matching the StarlettePathSecurityMiddlewarebehaviortest_double_slash_not_redirected_to_externalto expect400instead of403Files changed:
lib/streamlit/web/server/routes.py— AddedUnsafePathBlockHandlerclasslib/streamlit/web/server/server.py— Registered the handler as the first routee2e_playwright/web_server_test.py— Updated test to expect 400Test plan
web_server_test.py::test_double_slash_not_redirected_to_externalpasses for both Tornado and Starlette E2E test suites