-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restrict external navigation with goto
by default
#8775
Comments
Would be interesting to know how other frameworks (Nextjs, Remix, SolidStart) handle this |
We could forbid |
Unless someone jumps in with deeper knowledge on this before, I'm happy to do some research on this early this week.
👍 That would definitely be a good step to take, I guess there's zero good reasons why you would ever want to However with this specific vulnerability we accidentally created, even just the ability to create a link that forwards the user to any external site after logging in is also quite critical in itself, of course. The user would first click on a trustworthy link on the correct domain, and then potentially get forwarded to a phishing scam without realizing the domain had changed. Maybe blocking external links could be opt-in per call to |
Regarding Nextjs from what I saw in redirects (https://nextjs.org/docs/api-reference/next.config.js/redirects) logic, when external redirects are handled they check if the URLs are matching However they also have a helper function called |
You don't need to do anything fancy to tell if a URL is external or not, this is sufficient: function is_external(url) {
return new URL(url, location).origin !== location.origin;
} You can certainly make the case that @h0wl the Next.js API to compare against is
|
duh! that's so much better – changing our check to this for now :)
That's another great point, yeah. I suppose then instead of adding that |
We decided we just straight up disallow external navigation from |
URLs starting with |
Good point. AFAICT there's no way to express that in TypeScript though |
I'd probably just accept any string in that case |
@Rich-Harris It's actually quite possible in TypeScript, but IMO this will get too complicated for the use case and start to become burdensome. This kind of thing is better as a runtime check, as we'd probably also want to verify that |
* breaking: disallow external navigation using `goto` by default closes #8775 * do it here instead * adjust test * remove option, TODO tests * tweak message * Update .changeset/silent-games-taste.md * add a test, remove an obsolete test * fix test * prettier * fix * Update packages/kit/src/exports/public.d.ts Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> * Update packages/kit/src/runtime/client/client.js Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> * fix test * DRY out --------- Co-authored-by: Rich Harris <rich.harris@vercel.com> Co-authored-by: Rich Harris <richard.a.harris@gmail.com> Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
Merged #11207, so I'll close this |
Describe the problem
Currently, you can pass an absolute external path (e.g. "https://wikipedia.com") to the
goto
function, and it will happily navigate away to outside the SvelteKit app.Generally, this makes sense of course, but it caught me off-guard. Having used Nuxt before, where the
router.navigateTo
function forbids external navigation unless you explicitly setexternal
totrue
in its options, I implemented a mechanism that allows our sign-in page to push the user back to a route-guarded page using abackTo
URL parameter that would get appended to the sign-in page URL. Once the user signed in, the page would check whetherbackTo
is set to a path, and if yes pass its value togoto
.Recently, it was found that it was in fact possible to set this parameter to an absolute external URL, and it would happily push the user to that external page. Consequently, even
javascript:
URLs were possible, resulting in an XSS vulnerability.I understand that passing any user-editable string to
goto
was probably foolish on my part, but I didn't even consider the fact that external navigation would be possible at the time. Luckily, we caught this before going live on production, but I feel like this could be a common pitfall (especially given at least one other popular framework protects against it), with potentially severe consequences.Describe the proposed solution
Add a new paremeter
external
togoto
's options object, which is set tofalse
by default. Iffalse
, the function should ensure that the navigation would not push the user outside the current application, and throw an error if it would. Iftrue
, the current behavior should apply.See Nuxt.js'
navigateTo
function. https://nuxt.com/docs/api/utils/navigate-toAlternatives considered
Add the
external
parameter, but set it totrue
by default, so developers can opt-in to blocking external URLs when passing user-editable strings togoto
while avoiding a breaking change.Importance
would make my life easier
Additional Information
No response
The text was updated successfully, but these errors were encountered: