Summary:
Site at https://localhost:3000
, with Content-Security-Policy
value of default-src 'self' 'unsafe-inline' https://localhost:3001/https_index.html
contains iframe pointing at https://localhost:3001/index.html
. The contents of :3001/index.html
contain an <a href="mailto..."></a>
. Clicking that link fails: Refused to frame '' because it violates the following Content Security Policy directive...
. How can I change my CSP value to prevent this error; to open an new email in user's preferred email client (normal behavior of mailto
)? I am using Chrome1
Detail:
Similar but different than this question "mailto link not working within a frame chrome (over https) "
I think mine is not a duplicate because:
I cannot reproduce that bug, I see a console warning about mixed-content when I try to reproduce their steps:
Mixed Content: The page at 'https://localhost:3001/https_index.html' was loaded over HTTPS, but requested an insecure resource 'mailto:...'. This content should also be served over HTTPS.
My steps are specific; both my page & its iframe src are https
, but the page itself is served with a specific and restrictive Content-Security-Policy
(CSP
):
app.use(csp({
directives: {
defaultSrc: ["'self' 'unsafe-inline' https://localhost:3001/https_index.html"]
}
}));
Also the resulting error I can reproduce is different:
Refused to frame '' because it violates the following Content Security Policy directive: "default-src 'self' https://localhost:3001/https_index.html". Note that 'frame-src' was not explicitly set, so 'default-src' is used as a fallback.
target="_top"
to the link, the email client opens without error:
<a target="_top" href="mailto:...">email</a>
A similar fix works for another similar but different issue. However, this may1 sometimes open a new tabSo my question is specifically about the Content-Security-Policy
error (see above):
...Refused to frame '' because it violates the following Content Security Policy directive: ...
Notice it says frame ''
. The frame is identified as an empty string!
Normally if some resource violates CSP, the URL of the resource is identified; i.e.
Refused to laod the script 'http://evil.com/evil.js'...
And if the CSP
-violating URL is identified + provided I can use it; add it to my CSP
value for default-src
:
`app.use(csp({
directives: {
defaultSrc: ["http://evil.com/evil.js 'self' 'unsafe-inline' https://localhost:3001/https_index.html"]
}
}));`
But can I allow an exception for an href
value? Specifically for mailto
? I tried wildcards like mailto*
, but:
The source list for Content Security Policy directive 'default-src' contains an invalid source: 'mailto*'.
And I wonder if any wildcard would work anyway; does Chrome really consider the href="mailto..."
frame as an empty string? I suppose so, since it's not a URL per se; Chrome "wants" to launch an external application (i.e. Outlook) in the context of the iframe; who is bound to the CSP rules of its parent page...
Footnotes:
iframes
href, despite the value of CSP
. Internet Explorer also doesn't have the "new tab" problem, despite the value of sandbox
. IE 11.1914 will just give message:The fix of using target="_top"
may open a new tab , if you've sandbox
ed your iframe! (sandbox
is different than CSP
). I don't like the new tab. Chrome gave me this error...
Unsafe JavaScript attempt to initiate navigation for frame with URL 'http://localhost:3000/' from frame with URL 'https://localhost:3001/index.html'. The frame attempting navigation of the top-level window is sandboxed, but the flag of 'allow-top-navigation' or 'allow-top-navigation-by-user-activation' is not set.
... but opened a new tab, as well as the Outlook email client...
I did what the error suggested; modifying the value of the iframe
sandbox
attribute:
sandbox="allow-top-navigation allow-same-origin ..."
, and the mailto link worked (as before), but did not open an excessive new tab. Great!
Stumbled upon this question after encountering the same issue. There is surprisingly little documentation about this after hours of searching.
My first instinct was to do something like you were doing, mailto*
or mailto:*
.
What finally ended up working was omitting the wildcards, and altering the frame-src
directive as such:
frame-src 'self' mailto: tel: *.mydomain.com
tel:
links were also were broken in iframes.