Repository navigation
fix(browser): refuse malformed and credential-bearing authorities in Navigate - #1597
Conversation
…Navigate BrowserServiceImpl.navigateRefusal gated only the scheme, so a Navigate over IPC could still carry an authority composeApp's UrlOpenValidation refuses for URLs the OS hands BOSS - https://apple.com@evil.example among them. Navigate now applies the same authority rule after the scheme check: // must follow the scheme; the authority must be non-empty, free of spaces, backslashes, quotes, angle brackets and control characters, and free of @; and it must hold a non-empty host with an optional valid port (bracketed IPv6 aware, ASCII digits only). It judges the URL as an engine reads it, with tabs and newlines stripped, as the scheme check already did, so a tab cannot hide the @. Refusals name the rule, never the URL. Adapted from the authorityError approach in risa-labs-inc#916 by @KhushiTrivediii. The "response contract is not redacted" test now carries its secret in the query and fragment: userinfo can no longer reach the contract. Fixes risa-labs-inc#1591
|
@claude please review this exact head (f887104) for merge into dev. Check that the change is correct and complete for its stated goal, that tests cover the risk being fixed, and flag any security issues (secrets, injection, auth or approval bypass, path handling). Keep the review focused on this diff. |
|
Claude finished @fluck-boss's task in 4m 2s —— View job Review of
|
|
CI green on the refreshed head (ubuntu+windows), Claude review on the current head found no blocking or security issues, and a maintainer diff review is clean. Squash-merging to dev. |
Fixes #1591.
Problem
BrowserServiceImpl.navigateRefusalgated only the scheme. ANavigateover IPC could still carry an authority that composeApp'sUrlOpenValidation(the deep-link gate) refuses, includinghttps://apple.com@evil.example, where the credentials disguise the real host.Change
After the scheme check,
Navigatenow applies the same authority rule asUrlOpenValidation://must follow the scheme (https:example.comis refused, as the deep-link gate does)./,?or#) must be non-empty and free of spaces, NBSP, backslashes, quotes, angle brackets and control characters.@. Credentials are refused, not stripped.:or 0–65535 in ASCII digits. Bracketed IPv6 is handled, and fullwidth digits are rejected.It judges the URL as an engine reads it, with tabs and newlines stripped, the same form the scheme check already used. So
https://apple.com\t@evil.exampleis refused as the credential URL it becomes. Refusal messages name the rule and never echo the URL, keeping #911's "never the URL" logging contract.modules/boss-app-browsercan't depend on composeApp, so the rule is written here as file-scope functions, as #916 did. Adapted from @KhushiTrivediii'sauthorityErrorin #916, as the issue suggests.Tests
BrowserServiceImplTest: 15/15, plusktlintCheckanddetekt.@); 14 malformed authorities are refused; well-formed ones still navigate, including those a stricter parser would reject (localhost:3000,[::1]:8080,my_service, a bare:); and a refused authority emits no event and leaves the page alone.describeUridrops from the log), since userinfo can no longer reach the contract.@check, the port check or the whole authority gate each fail the matching tests.