I assume that this is just a simple misunderstanding of the spec. However, I'm having an issue with including scripts in iFrames protected by sandboxing. Specifically, the code I am dealing with is below.
In top.html:
<iframe src="framed.html" sandbox="allow-scripts"></iframe>
In framed.html
...
<head>
<meta http-equiv="Content-Security-Policy" content="script-src example.com">
<script src="http://example.com/script.js"></script>
</head>
...
When running this file in Chrome, it gives me the error:
Refused to load the script 'http://example.com/script.js' because
it violates the following Content Security Policy directive:
"script-src localhost:9000".
Why is it blocking the script from loading? I know that without allow-same-origin
, the iFrame gets a completely unique origin that is not equal to any other origin. Therefore, script-src 'self'
wouldn't work. However, I am trying to load the script from an origin explicitly called for in the CSP. Thoughts?
Update: Created JSFiddle to showcase the issue.
When you use a sandboxed page with a unique origin, you can't put a host without scheme in the CSP, that's why the policy is violated. Use script-src https://example.com or script-src http://example.com or even script-src https://example.com https://example.com , and the CSP will correctly be relaxed (note that the CSP is whitelist-based, by default most things are disallowed).
As the grammar from the CSP specification shows, the scheme in a CSP directive is optional:
; Schemes: "https:" / "custom-scheme:" / "another.custom-scheme:"
scheme-source = scheme-part ":"
; Hosts: "example.com" / "*.example.com" / "https://*.example.com:12/path/to/file.js"
host-source = [ scheme-part "://" ] host-part [ port-part ] [ path-part ]
scheme-part = scheme
; scheme is defined in section 3.1 of RFC 3986.
host-part = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
host-char = ALPHA / DIGIT / "-"
port-part = ":" ( 1*DIGIT / "*" )
path-part = path-abempty
; path-abempty is defined in section 3.3 of RFC 3986.
But a sandboxed frame without the allow-same-origin
token will have a null
origin, and the URL matching algorithm does not allow scheme-less directives to match (relevant parts of the algorithm shown below):
6.6.1.6. Does url match expression in origin with redirect count?
Given a URL (url), a source expression (expression), an origin (origin), and a number (redirect count), this algorithm returns "Matches" if url matches expression, and "Does Not Match" otherwise.
...
If expression matches the host-source grammar:
If url’s host is null
, return "Does Not Match".
- If url’s host is
null
, return "Does Not Match".
If expression does not have a scheme-part, then return "Does Not Match" unless one of the following conditions is met:
- origin’s scheme is url’s scheme
- origin’s scheme is "http", and url’s scheme one of "https", "ws", or "wss".
- origin’s scheme is "https", and url’s scheme is "wss".
In the given example:
origin
is null
(because of the use of sandbox
without allow-same-origin
).
- url is
http://example.com/script.js
The null
origin's scheme does not match any of the last three cases, so the host name without scheme won't match any URL, and therefore the policy is violated.