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

Interaction of CSP and javascript: URLs in iframe src is not defined anywhere #127

Closed
bzbarsky opened this issue Oct 13, 2016 · 12 comments
Closed
Assignees

Comments

@bzbarsky
Copy link

Consider this testcase:

<!DOCTYPE html>
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
<iframe src="javascript:'Why does this text not show up?'"></iframe>

The text does not show up in either Gecko or Blink, but I see nothing in either the HTML spec or the CSP spec that would produce this behavior.

@shekyan
Copy link
Contributor

shekyan commented Oct 13, 2016

It is implied by https://w3c.github.io/webappsec-csp/#match-url-to-source-expression, javascript: has to be either explicitly safelisted or protected resource should be served from javascript:

@bzbarsky
Copy link
Author

Why would that algorithm be invoked at all in this case? It wouldn't be, and it's not, as you can tell from this testcase:

<!DOCTYPE html>
<meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline'">
<iframe src="javascript:'This text DOES show up!'"></iframe>

@shekyan
Copy link
Contributor

shekyan commented Oct 13, 2016

Why would that algorithm be invoked at all in this case?

Because src attribute of iframe element is governed by frame-src, with fallback to worker-src, with fallback to default-src.
In your example, script-src 'self' implies that frame-src source-list is *, which falls under https://w3c.github.io/webappsec-csp/#match-url-to-source-expression : javascript: is a non-network scheme, so, it doesn't match.

That's what SHOULD happen. It doesn't though, as both Firefox and Chrome do not implement this algorithm. Instead, it is blocked by JavaScript pre-evaluation check. Chrome treats it as inline script and blocks it, while FF does not thus it isn't blocked.

I agree that spec should explicitly say that javascript: is treated as inline script.

@bzbarsky
Copy link
Author

Because src attribute of iframe element is governed by frame-src, with fallback to worker-src, with fallback to default-src.

OK, true.

In your example, script-src 'self' implies that frame-src source-list is *

Yes, ok, agreed.

which falls under https://w3c.github.io/webappsec-csp/#match-url-to-source-expression : javascript: is a non-network scheme, so, it doesn't match.

Note that https://www.w3.org/TR/CSP2/#match-source-expression says something quite different from that editor's draft; I assume that's what's shipping in browsers right now.

The editor's draft will likely need to be adjusted to avoid breaking existing content in this matter...

Chrome treats it as inline script and blocks it, while FF does not thus it isn't blocked.

Uh... Chrome and FF have identical behavior (to each other) on both of my testcases.

I agree that spec should explicitly say that javascript: is treated as inline script.

That's certainly what shipping UAs are doing. Though there are open questions as to which document's CSP they're using for it, I bet, since none of this is very specified.

@shekyan
Copy link
Contributor

shekyan commented Oct 13, 2016

Note that https://www.w3.org/TR/CSP2/#match-source-expression says something quite different from that editor's draft;

Yep, https://w3c.github.io/webappsec-csp/#changes-from-level-2 step 9 lists that change as a breaking change.

Uh... Chrome and FF have identical behavior (to each other) on both of my testcases.

My bad, restarting FF 49 brought it to the same behavior as Chrome.

I'll report issues for both browsers on frame-src behavior. I think CSP3 is is doing the right thing by blocking by default non-network schemes.

@annevk
Copy link
Member

annevk commented Oct 14, 2016

I don't think we'd end up blocking since CSP depends on Fetch and HTML's navigate bypasses Fetch for certain schemes, including javascript. So the solution here may need to be more involved.

@bzbarsky
Copy link
Author

Ah, good point. That explains part of why frame-src has no effect here, no matter what UAs are implementing under the hood.

The fetch thing shouldn't affect the script-src 'inline' behavior, though, since that doesn't hook into CSP via fetch (e.g. it applies to inline <script> which has no fetch involved at all). Something just needs to define that javascript: evaluation is subject to the relevant CSP checks.

So I figured I'd check how the inline <script> case is handled. It's handled by HTML in https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script step 11. Similarly, event handler attributes are handled in https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-attributes:event-handler-content-attributes-3 step 1.

So sounds like this needs to be handled over in HTML at least in part. Filed whatwg/html#1901 for that.

That said, CSP presumably needs to define a type to pass to https://w3c.github.io/webappsec-csp/#should-block-inline in this situation. Right now the only types https://w3c.github.io/webappsec-csp/#ref-for-directive-inline-check-2 recognizes are "script attribute" and "script", and the behavior for either one doesn't seem right for this case. Leaving this issue open for defining that.

@bzbarsky
Copy link
Author

bzbarsky commented Oct 14, 2016

Note also that it's not clear to me whether this check should be done on element attributes (iframe@src, object@data, etc) or during the actual navigation. Depends on how you want CSP to handle assignment of location.href to a javascript: URL, for example. This affects whether the element argument to https://w3c.github.io/webappsec-csp/#should-block-inline makes any sense.

Right now at least Gecko handles it during navigation.

@mikewest mikewest self-assigned this Nov 8, 2016
mikewest added a commit that referenced this issue Nov 8, 2016
@bzbarsky noted in #127 that we're not handling
the inline checks for navigations to `javascript:` URLs correctly.
This patch refactors the inline behavior checks in order to
support a future patch to HTML in whatwg/html#1901 to wire [1]
up to CSP.

[1]: https://html.spec.whatwg.org/multipage/browsers.html#navigating-across-documents:javascript-protocol
mikewest added a commit that referenced this issue Nov 9, 2016
@bzbarsky noted in #127 that we're not handling
the inline checks for navigations to `javascript:` URLs correctly.
This patch refactors the inline behavior checks in order to
support a future patch to HTML in whatwg/html#1901 to wire [1]
up to CSP.

[1]: https://html.spec.whatwg.org/multipage/browsers.html#navigating-across-documents:javascript-protocol
mikewest added a commit that referenced this issue Nov 10, 2016
@bzbarsky noted in #127 that we're not handling
the inline checks for navigations to `javascript:` URLs correctly.
This patch refactors the inline behavior checks in order to
support a future patch to HTML in whatwg/html#1901 to wire [1]
up to CSP.

[1]: https://html.spec.whatwg.org/multipage/browsers.html#navigating-across-documents:javascript-protocol
@mikewest
Copy link
Member

This was addressed in a few commits against CSP and HTML in the linked bugs.

@bzbarsky
Copy link
Author

@mikewest Did we add web platform tests around this stuff? For the fact that unsafe-inline controls this, and the fact that script-src does not, and for which document's CSP gets used?

@mikewest
Copy link
Member

@bzbarsky: We upstreamed https://github.com/w3c/web-platform-tests/blob/master/content-security-policy/navigation/to-javascript-url.html which verifies the 'unsafe-inline' bit and that the securitypolicyviolation event fires in the correct document. Looking at it again, though, it doesn't verify that frame-src does not affect the navigation. I'll add something to that effect.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue May 11, 2017
As noted in w3c/webappsec-csp#127, we should
have a test verifying that navigation to 'javascript:' is controlled
via 'script-src' and not 'frame-src'.

R=foolip@chromium.org

Review-Url: https://codereview.chromium.org/2880563002
Cr-Commit-Position: refs/heads/master@{#470932}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue May 11, 2017
As noted in w3c/webappsec-csp#127, we should
have a test verifying that navigation to 'javascript:' is controlled
via 'script-src' and not 'frame-src'.

R=foolip@chromium.org

Review-Url: https://codereview.chromium.org/2880563002
Cr-Commit-Position: refs/heads/master@{#470932}
scheib pushed a commit to scheib/chromium that referenced this issue May 11, 2017
As noted in w3c/webappsec-csp#127, we should
have a test verifying that navigation to 'javascript:' is controlled
via 'script-src' and not 'frame-src'.

R=foolip@chromium.org

Review-Url: https://codereview.chromium.org/2880563002
Cr-Commit-Position: refs/heads/master@{#470932}
@bzbarsky
Copy link
Author

@mikewest Looks good, thanks!

ryandel8834 added a commit to ryandel8834/WebAppSec-CSP that referenced this issue Aug 13, 2022
@bzbarsky noted in w3c/webappsec-csp#127 that we're not handling
the inline checks for navigations to `javascript:` URLs correctly.
This patch refactors the inline behavior checks in order to
support a future patch to HTML in whatwg/html#1901 to wire [1]
up to CSP.

[1]: https://html.spec.whatwg.org/multipage/browsers.html#navigating-across-documents:javascript-protocol
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

4 participants