Skip to content

Refuse joins whose url has no host instead of crashing - #4490

Merged
SteffenDE merged 1 commit into
phoenixframework:mainfrom
Arsenalist:fix-hostless-route-join
Nov 5, 2026
Merged

SteffenDE merged 1 commit into
phoenixframework:mainfrom
Arsenalist:fix-hostless-route-join

Conversation

@Arsenalist

@Arsenalist Arsenalist commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

If a join's url or redirect parses to a URI with no host, the LiveView channel crashes with a CaseClauseError in verified_mount/8. This happens with "" or a relative path such as "clock-live-session".

session_route/3 still resolves such a URL to an internal route. When that route is in the same live session, authorize_session/3 accepts it. Then this code runs:

case route do
  %Route{uri: %URI{host: host}} = route when byte_size(host) <= @max_host_size -> ...
  nil -> ...
end

byte_size(nil) fails the guard, and there is no fallback clause.

In production we see this from Meta's crawler. On live navigation it sends "redirect" => "", presumably because its DOM doesn't resolve anchor.href to an absolute URL. We logged several hundred of these crashes in two weeks. This may also be the server side of #2518.

Change

session_route/3 now returns nil for routes whose URI has no host. The join is refused as unauthorized, so the client falls back to a full page load. That's the same path as navigating to a route in a different live session.

Test

Added "refused with a url without host" to the live_redirect tests in navigation_test.exs. It fails with the CaseClauseError before the change and passes after it. The full suite passes.

🤖 Generated with Claude Code

A join with a "url" or "redirect" that parses without a host (for
example "" or a relative path) can still match an internal route in the
same live session. verified_mount/8 then raised a CaseClauseError, since
its byte_size(host) guard fails on nil and there is no fallback clause.
Treat such urls as unmatched so the join is refused as unauthorized.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013C832oaAyjJ711i9QTCVjR
@SteffenDE
SteffenDE merged commit be50ec9 into phoenixframework:main Nov 5, 2026
9 checks passed
@SteffenDE SteffenDE mentioned this pull request Nov 5, 2026
@SteffenDE

Copy link
Copy Markdown
Member

Thank you!

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.

2 participants