Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting iframe into page with restrictive Content Security Policy

I want to create a browser extension which creates a sidebar. Chrome does not have a first-class sidebar, and so we must instead put an iframe in the page. However, this breaks on many pages due to content security policy. E.g. GitHub uses a CSP, which does not allow iframes from other sites to be embedded within it. E.g. if you try to put the capitalone.com website in an iframe on GitHub you get the following:

Refused to frame 'https://www.capitalone.com/' because it violates the following Content Security Policy directive: "frame-src 'self' render.githubusercontent.com www.youtube.com assets.braintreegateway.com".

Here's a simple browser extension to reproduce that:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {   if (changeInfo.status === 'complete') {    chrome.tabs.executeScript(tabId, { code: 'document.body.innerHTML=\'<iframe style=\"width:600px; height:600px\" src=\"https://www.capitalone.com/\"></iframe>\' + document.body.innerHTML;' }, function() {      console.log('Iframe injection complete');    })   } }.bind(this)); 

Yet, according to Wikipedia, a browser extension should be able to inject an iframe despite any content security policy:

According to the CSP Processing Model,[20] CSP should not interfere with the operation of browser add-ons or extensions installed by the user. This feature of CSP effectively allows any add-on or extension to inject script into websites, regardless of the origin of that script, and thus be exempt from CSP policies.

Is there some other way that I should be injecting an iframe besides what I'm doing?

like image 811
Ben McCann Avatar asked Jul 08 '14 21:07

Ben McCann


People also ask

Does CSP apply to iframes?

iframe elements have a csp attribute, defined in § 2.1 <iframe>'s csp attribute. Each browsing context has a required CSP, defined in § 2.4. 1 Browsing Context's Required CSP.

Are iframes a security risk?

iframes are a great option to keep your users more engaged. But, when you use an iframe, you're handling content from a third-party source that you have no control over. As a result, iframes often pose security threats to the applications.

How do I fix refused connection in iframe?

You cannot fix this from Power Apps Portal side. Most probably web site that you try to embed as an iframe doesn't allow to be embedded. You need to update X-Frame-Options on the website that you are trying to embed to allow your Power Apps Portal (if you have control over that website).


2 Answers

The inability to insert an external iframe in Chrome is a bug (crbug.com/408932).

If you want to embed an external frame in an external website, then it must be loaded in a frame that is packaged with your extension.

manifest.json

{     "name": "Embed external site",     "version": "1",     "manifest_version": 2,     "content_scripts": [{         "js": ["contentscript.js"],         "matches": ["*://*/*"],         "all_frames": true     }],     "web_accessible_resources": [         "frame.html"     ] } 

Do NOT use chrome.tabs.onUpdated + chrome.tabs.executeScript if you want a content script to always be inserted in a document. Your implementation is flawed and can cause the script to be run multiple times. Instead, you should declare the content script in the manifest file.

(remove "all_frames": true if you don't want to insert the frame in every subframe.)

contentscript.js

// Avoid recursive frame insertion... var extensionOrigin = 'chrome-extension://' + chrome.runtime.id; if (!location.ancestorOrigins.contains(extensionOrigin)) {     var iframe = document.createElement('iframe');     // Must be declared at web_accessible_resources in manifest.json     iframe.src = chrome.runtime.getURL('frame.html');      // Some styles for a fancy sidebar     iframe.style.cssText = 'position:fixed;top:0;left:0;display:block;' +                            'width:300px;height:100%;z-index:1000;';     document.body.appendChild(iframe); } 

frame.html

<style> html, body, iframe, h2 {     margin: 0;     border: 0;     padding: 0;     display: block;     width: 100vw;     height: 100vh;     background: white;     color: black; } h2 {     height: 50px;     font-size: 20px; } iframe {     height: calc(100vh - 50px); } </style> <h2>Displaying https://robwu.nl in a frame</h2> <iframe src="https://robwu.nl/"></iframe> 

It is important to observe that I loaded an https site in the frame. If you attempt to load an HTTP site in the frame, then the mixed content policy will block the frame from being loaded if one of the parent frames is an https page.

Replace https://robwu.nl/ with http://example.com/ and the frame will remain blank on https pages such as https://github.com. Simultaneously, the following message will be printed to the console.

[blocked] The page at 'https://github.com/' was loaded over HTTPS, but ran insecure content from 'http://example.com/': this content should also be loaded over HTTPS

like image 66
Rob W Avatar answered Sep 20 '22 21:09

Rob W


Rob W 's answer is correct. You can follow this https://transitory.technology/browser-extensions-and-csp-headers/. I 've successfully make it work in my Chrome extension https://github.com/onmyway133/github-chat

Note that I use Chrome 59, so I can use most of ES6 features

Declare in manifest

"web_accessible_resources": [   "iframe.html",   "scripts/iframe.js" ] 

Create an iframe in window.onload event

let url    = decodeURIComponent(window.location.search.replace('?url=', '')) let iframe = document.createElement('iframe') iframe.src = url  iframe.id = 'github-chat-box-iframe-inner' iframe.style.width = '100%' iframe.style.height = '350px' iframe.style.border = '0px'  window.onload = () => {   document.body.appendChild(iframe) } 
like image 37
onmyway133 Avatar answered Sep 19 '22 21:09

onmyway133