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

Unable to frame site whose CSP contains frame-ancestors * inside <iframe> or <webview> #26369

Closed
3 tasks done
joyceerhl opened this issue Nov 7, 2020 · 5 comments
Closed
3 tasks done

Comments

@joyceerhl
Copy link

Preflight Checklist

  • I have read the Contributing Guidelines for this project.
  • I agree to follow the Code of Conduct that this project adheres to.
  • I have searched the issue tracker for an issue that matches the one I want to file, without success.

Issue Details

  • Electron Version:
    • 10.1.5, 9.2.1, 4.2.12
  • Operating System:
    • Windows_NT x64 10.0.19042
  • Last Known Working Electron version:
    • N/A

Expected Behavior

According to the content security policy specification, Electron should be able to frame a website whose response headers contain the frame-ancestors * CSP directive by setting its URL as the source of an <iframe> or a <webview>. From https://w3c.github.io/webappsec-csp/2/#match-source-expression, at minimum http URLs should be treated as a match, not a violation, for a CSP directive whose source list is *:

If the source expression consists of a single U+002A ASTERISK character (*), and url’s scheme is not one of blob, data, filesystem, then return does match.

Actual Behavior

Electron reports a CSP violation for <iframe>s or <webview>s whose source URL points to a website which sets the frame-ancestors * directive in its response headers.

To Reproduce

Start a simple web server which sets the frame-ancestors * CSP directive in its response headers. For example, to do this with Python:

  1. Install Python 3 from https://www.python.org/downloads/, making sure to add it to your PATH during the install configuration step
  2. Install the Python flask module with python -m pip install flask
  3. Clone this repo: https://github.com/joyceerhl/maybe-bug. The directory root contains a simple server app in Python, app.py
  4. In the root of the repo, run python -m flask run to start app.py
  5. Visit localhost:5000 in Chrome or Edge to confirm that the server started successfully:
    image
  6. cd into the electron-quick-start subdirectory. This is identical to https://github.com/electron/electron-quick-start, except that index.html contains an <iframe> whose source is localhost:5000:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <iframe
      width="700"
      height="350"
      src="http://localhost:5000"
      frameborder="0"
      allowfullscreen
    ></iframe>
  </body>
</html>
  1. Run npm install and then npm start to launch the Electron app
  2. Electron reports a CSP violation and refuses to frame the website running at http://localhost:5000:
    image

If you comment out the line that sets the CSP in app.py and restart the server, Electron has no trouble framing the website:
image
This seems odd as frame-ancestors * should be equivalent to omitting the frame-ancestors directive altogether. From https://w3c.github.io/webappsec-csp/2/#directive-frame-ancestors:

The term allowed frame ancestors refers to the result of parsing the frame-ancestors directive’s value as a source list. If a frame-ancestors directive is not explicitly included in the policy, then allowed frame ancestors is "*".

Additional Information

I don't have control over the source code for the website that I'm framing (the broader context for this investigation is that I'm trying to frame the Tensorboard webapp, which is started and served locally, in an Electron environment), or I'd simply remove the frame-ancestors * directive as a workaround. I'm filing this bug on Electron because Chromium-based browsers don't seem to exhibit this behavior, so this seemed like the right spot, but please let me know if I should file this elsewhere. Thanks so much for your help! 😊

@nornagon
Copy link
Member

does this also occur in Chrome?

@joyceerhl
Copy link
Author

@nornagon, nope, Chrome displays it without trouble, and so does Edge:

image

stephanwlee pushed a commit to tensorflow/tensorboard that referenced this issue Nov 17, 2020
This PR essentially reverses #2797.

Currently this doesn't work because the `frame-ancestors *` directive prevents VS Code from framing TensorBoard. This is because VS Code is an Electron application, and Electron appears to be unable to frame websites which set `frame-ancestors *` in its response headers: electron/electron#26369

If I'm reading the CSP specification correctly, omitting the frame-ancestors directive altogether is equivalent to setting `frame-ancestors *`, so to my knowledge this PR should not result in a behavior change for environments which correctly implement the CSP spec. From https://w3c.github.io/webappsec-csp/2/#directive-frame-ancestors:

> The term allowed frame ancestors refers to the result of parsing the frame-ancestors directive’s value as a source list. If a frame-ancestors directive is not explicitly included in the policy, then allowed frame ancestors is "*".
@nornagon
Copy link
Member

@joyceerhl it looks like in Chrome you're hosting the iframe in the same origin as the child, whereas in Electron you're hosting it from a file:// URL. I can reproduce the error in Chromium when the page hosting the iframe is a file: or data: URL. So I don't think this is an Electron bug.

BTW, I made a version of your repro case using Node.js's http module that can be run using Electron Fiddle: https://gist.github.com/514e2e53bca217dd28c1e6488efe7f1b since that was easier for me than installing Flask.

wchargin pushed a commit to tensorflow/tensorboard that referenced this issue Jan 14, 2021
This PR essentially reverses #2797.

Currently this doesn't work because the `frame-ancestors *` directive prevents VS Code from framing TensorBoard. This is because VS Code is an Electron application, and Electron appears to be unable to frame websites which set `frame-ancestors *` in its response headers: electron/electron#26369

If I'm reading the CSP specification correctly, omitting the frame-ancestors directive altogether is equivalent to setting `frame-ancestors *`, so to my knowledge this PR should not result in a behavior change for environments which correctly implement the CSP spec. From https://w3c.github.io/webappsec-csp/2/#directive-frame-ancestors:

> The term allowed frame ancestors refers to the result of parsing the frame-ancestors directive’s value as a source list. If a frame-ancestors directive is not explicitly included in the policy, then allowed frame ancestors is "*".
wchargin added a commit to tensorflow/tensorboard that referenced this issue Jan 14, 2021
Backport of #4332 to 2.4. Cf. #4547.

---

This PR essentially reverses #2797.

Currently this doesn't work because the `frame-ancestors *` directive prevents VS Code from framing TensorBoard. This is because VS Code is an Electron application, and Electron appears to be unable to frame websites which set `frame-ancestors *` in its response headers: electron/electron#26369

If I'm reading the CSP specification correctly, omitting the frame-ancestors directive altogether is equivalent to setting `frame-ancestors *`, so to my knowledge this PR should not result in a behavior change for environments which correctly implement the CSP spec. From https://w3c.github.io/webappsec-csp/2/#directive-frame-ancestors:

> The term allowed frame ancestors refers to the result of parsing the frame-ancestors directive’s value as a source list. If a frame-ancestors directive is not explicitly included in the policy, then allowed frame ancestors is "*".

Co-authored-by: Joyce Er <joyceerhuiling@gmail.com>
@zdnk
Copy link

zdnk commented Jun 5, 2022

I have the same issue. What would be the right solution for this?
It works in debug mode with live reload, but not in production build. Also opening it with chrome as file:// works which is weird.

@AlexPetrusca
Copy link

You can set an onHeadersReceived listener to filter out the specific 'content-security-policy' checks you want to remove.

Here I simply remove all of them:

win.webContents.session.webRequest.onHeadersReceived({ urls: [ "*://*/*" ] }, (d, c) => {
  if (d.responseHeaders['Content-Security-Policy']) {
    delete d.responseHeaders['Content-Security-Policy'];
  } else if (d.responseHeaders['content-security-policy']) {
    delete d.responseHeaders['content-security-policy'];
  }
  c({cancel: false, responseHeaders: d.responseHeaders});
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants