Skip to content
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

Allow navigation to only whitelisted URLs via navigate-to #125

Closed
april opened this issue Oct 6, 2016 · 13 comments
Closed

Allow navigation to only whitelisted URLs via navigate-to #125

april opened this issue Oct 6, 2016 · 13 comments
Assignees
Milestone

Comments

@april
Copy link
Contributor

april commented Oct 6, 2016

There's been some mild discussion around whether or not to add a directive that would restrict what URLs a given page can navigate to. Let's get it started!

@april
Copy link
Contributor Author

april commented Oct 6, 2016

The idea is certainly interesting, but I suspect it will end up by the most complex CSP directive by a country mile for browsers to implement.

  • Let's say there's an <a> with a href to a site that is non-whitelisted. Do browsers simply remove the styling for a to make it appear as not a link? Can you click it but it does nothing? Do browsers pop up a warning?
  • That's actually the easy case. What happens if a page tries to navigate a user to a non-whitelisted via JavaScript? For example, you select a menu item and it tries to send you to an error page. Obviously the navigation would fail, but would the code continue executing?
  • Let's say you're allowing advertisements, and you've forced your advertiser to choose their list of safe domains. They choose safeads.com. So they include a link to safeads.com and that 302 redirects to evilads.com. Is the redirection blocked? What happens here? What about meta redirects? Same thing? What about a bit of JavaScript that changes the location 30 seconds later?

I think this idea is overall great for sites that run advertisements or otherwise let users embed URLs, but I think it will be difficult to make work effectively.

@mikewest
Copy link
Member

mikewest commented Oct 6, 2016

Let's say there's an <a> with a href to a site that is non-whitelisted. Do browsers simply remove the styling for a to make it appear as not a link? Can you click it but it does nothing? Do browsers pop up a warning?

If browsers would like to do something like that, they may. As written, clicking it would end up starting a navigation, blocking the request by simulating a network error response from Fetch, thereby rendering some sort of error page. We could certainly change that to block the request by treating it as a 204 (e.g. no navigation actually takes place, and you just stay on the page you were on to begin with). I don't have a strong preference, but I think navigating to an error page is a safe default.

That's actually the easy case. What happens if a page tries to navigate a user to a non-whitelisted via JavaScript? For example, you select a menu item and it tries to send you to an error page. Obviously the navigation would fail, but would the code continue executing?

Whether the code continues executing depends on the navigation behavior we choose above. As written, the page would be unloaded, so the script would stop executing. If we moved to a 204-style behavior, the script would continue executing.

Let's say you're allowing advertisements, and you've forced your advertiser to choose their list of safe domains. They choose safeads.com. So they include a link to safeads.com and that 302 redirects to evilads.com. Is the redirection blocked?

Yes. HTTP redirects would be blocked, as we do the check in the middle of the navigation algorithm (step 6 of https://html.spec.whatwg.org/multipage/browsers.html#process-a-navigate-fetch). That algorithm recurses on itself (in step ~9) for redirect responses, so each item in the redirect chain would be tested against the policy.

What about meta redirects? Same thing? What about a bit of JavaScript that changes the location 30 seconds later?

Nope. Both of these would end up with the user landing on evil.com, as they're not part of the same chain of navigation.

What I've heard from anti-malvertising folks is that the expected landing page is generally safe. There are certainly cases where folks are cloaking a declared landing page's intent from the advertiser in some way, but those are the minority of cases. Bad behavior generally results from sending users somewhere else entirely (and generally doesn't wait for a user to click on anything: window.top.location = "https://evil.com/" (or, worse, itmss://itunes.apple.com/...)). The anecdotes I've heard point to getting the user to a trusted origin as being enough to substantially mitigate badness.

@mikewest mikewest self-assigned this Oct 6, 2016
@mikewest mikewest added this to the CSP3 CR milestone Oct 6, 2016
@april
Copy link
Contributor Author

april commented Oct 6, 2016

What I've heard from anti-malvertising folks is that the expected landing page is generally safe. There are certainly cases where folks are cloaking a declared landing page's intent from the advertiser in some way, but those are the minority of cases.

Sure, they're the minority of cases now. I suspect that should Google Adwords (or whatever advertiser) start using navigate-to, that they would immediately become the majority of cases. If they're having trouble detecting ads that link or redirect to things like itmss://itunes.apple.com/... now, I can only imagine it's going to be 100x harder with dubious landing pages.

That's not to say that I don't think that navigate-to is a bad idea, it's just that I want to make sure that it actually solves a problem and doesn't end up like anti-virus where it's something that fails completely when something falls just a little bit outside of the known patterns.

@april
Copy link
Contributor Author

april commented Oct 6, 2016

I've been mulling this around in my head, and I think I have an idea that might work.

  • If example.com sets a navigate-to of safeads.com, then the navigated-to page on safeads.com is prohibited from any further redirection until it receives user interaction, such as a click or keyboard input. This includes HTTP 301/302 redirects, setting location via window.location or via meta refresh tags.

This would prevent a landing page on safeads.com from doing a redirect (either immediately or after some delay) to evilads.com until the user commits some sort of interaction on the page, at the very least indicating that they don't think safeads.com is immediately doing something bad. It's not foolproof, but it would possibly lower the success rate such that it wouldn't be worthwhile to engage in a campaign like that.

This would require browsers to track state across page navigations, but hopefully would go a long ways towards solving both halves of the malvertising problem.

@mikewest
Copy link
Member

mikewest commented Oct 7, 2016

@marumari: Thanks! This isn't a crazy idea: I think gating navigation on user gesture is a reasonable thing for a page to ask for, and was actually on my list of things to tack onto either this or feature policy or wherever it makes sense.

For my own clarity, you'd basically want to set a flag on the new page that blocked navigation, and clear it if/when a user interacted with the page (similar to the heuristics we're using for the popup blocker)?

/cc @hillbrad who's been watching some user-gesture-and-navigation Chrome changes warily.

@april
Copy link
Contributor Author

april commented Oct 7, 2016

For my own clarity, you'd basically want to set a flag on the new page that blocked navigation, and clear it if/when a user interacted with the page (similar to the heuristics we're using for the popup blocker)?

Yep, that's exactly it!

@dhausknecht
Copy link

I see navigation-to as a bit to targeted with ads in mind. there are many other ways to navigate, for example the already mentioned <meta http-equiv="refresh" content="...">. I am certain that the (justified) intuition of web developers will be that any navigation will be controlled by it. The result is yet again more confusion through CSP and useless policies out there. So I suggest a name change to something that makes this limitation clearer. What about like link-navigation or something similar?

The unfortunate huge problem with refresh is that you do not know when it is triggered, that is you would need to enforce a navigation policy from context A in another context B. However B certainly doesn't want to be restricted, does not know that it is restricted and it is very likely that this would also break B. In short, you cannot do this (and this is probably why you don't do that now).
But there are other things like <a rel="noopener" ...>..</a> which you might want to enforce on uncontrollable content while not having side effects. Do you see reason in adding this and related ones as keywords to automatically apply this to navigation attempts?

I didn't understand if you would need to whitelist all possible intermediate redirection URLs or is only the landing page URL that matters?

@hillbrad
Copy link
Contributor

This user gesture requirement seems OK, given that it needs to be explicitly opted into by the loading frame. The Chrome interventions make me sad because they are being imposed on all resources with no way to opt-out.

@eligrey
Copy link
Member

eligrey commented Jan 9, 2018

This parameter would help close one of the few remaining data exfiltration holes not currently covered by CSP. I feel like it would serve as a useful defense in depth addition for sensitive sites.

@eligrey
Copy link
Member

eligrey commented Jan 17, 2018

Is anyone interested in speccing this eventually?

@lubin2010
Copy link

@eligrey There is some ongoing work on trying to spec this in a reasonable way, eg., https://w3c.github.io/webappsec-csp/#navigation-to, and https://lists.w3.org/Archives/Public/public-webappsec/2017Dec/0000.html.

@annevk
Copy link
Member

annevk commented Feb 16, 2018

Most notably #290 is in progress.

@andypaicu
Copy link
Collaborator

Not sure how it's related to navigate-to, the showed bypass is using a prerender (for Chrome), no navigation occurs. navigate-to also does not fallback on default-src so the stated policy won't block any navigations anyway.

ryandel8834 added a commit to ryandel8834/WebAppSec-CSP that referenced this issue Aug 13, 2022
It seems like there are no more objections and corrections.

This fixes w3c/webappsec-csp#125.
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

No branches or pull requests

8 participants