Search code examples
javascriptgoogle-chromeiframeevernote

How Do I Set Value of Elements in iframe?


I need to set the value attribute of several elements in the document of an iframe. I am able to easily do this from Chrome Tools Console. But the same commands do NOT work from a JavaScript injected into the page by Keyboard Maestro or AppleScript.

The iframe is generated by a Chrome extension: Evernote Web Clipper. In the below examples, I have already invoked the Evernote Web Clipper.

enter image description here

This script/commands work from Chrome Console, after I have selected the iframe document:

var remElem = document.getElementById("comments");
remElem.value = "KM This is a test";
var titleElem = document.getElementById("title")
titleElem.value = 'KMTEST title'

I suspect that I first need to get or select the iframe document before I run the above script. How do I do this?

I have tried many different SO solutions, and none of them work.

Here is a screenshot of the main document in Chrome Tools:

Main Document in Chrome Tools

Screenshot of iframe document in Chrome Tools:

enter image description here

Here is what I have tried, unsuccessfully:

// *** NONE of These Work ***

//--- Method 1 ---
var frame = window.frames[‘frame1’];
var documentObj = frame.document;
var element = documentObj.getElementsByName(‘frame1Text’); 

//--- Method 2 ---
var frame = document.getElementById(‘myframe1’);
var documentObj = frame.contentWindow.document;
var element = documentObj.getElementById(‘frame1Text’);

//--- Method 3 ---
window.frames[1].document.getElementById('someElementId')

For example, from Chrome Tools, when I have the main document selected:

//--- From Chrome Tools with Main document selected ---

enFrm = document.getElementById("evernoteGlobalTools")
/*RESULTS
<iframe id=​"evernoteGlobalTools" src=​"chrome-extension:​/​/​pioclpoplcdbaefihamjohnefbikjilc/​content/​global_tools/​global_tools.html" class=​"evernoteClipperVisible" style=​"height:​ 528px !important;​">​</iframe>​
*/

oDoc = enFrm.contentWindow.document;
/* ERROR
VM882:1 Uncaught DOMException: Blocked a frame with origin "http://forum.latenightsw.com" from accessing a cross-origin frame.
    at <anonymous>:1:27
(anonymous) @ VM882:1
*/

oDoc = enFrm.contentWindow.document;

/* ERROR
VM892:1 Uncaught DOMException: Blocked a frame with origin "http://forum.latenightsw.com" from accessing a cross-origin frame.
    at <anonymous>:1:27
*/

Any/All suggestions/ideas gratefully accepted.


Solution

  • The error you are facing:

    Uncaught DOMException: Blocked a frame with origin "http://forum.latenightsw.com" from accessing a cross-origin frame.

    clearly states that your code has been blocked due to a Cross-Origin Resource Sharing restriction (A.K.A. Content Security policy or evn CORS).

    Your domain forum.latenightsw.com is quite rightly considered not the same when compared to chrome-extension:​/​/​pioc… (main page versus extension's injected IFrame's domain ). Accessing the IFrame's DOM in such a situation would be a HUGE security flaw.

    I fear there is no realistic solution that would let you run this code from the main page Javascript context.

    If you were in control of the chrome extension, you could try adding your domain as a host permission in the manifest file (If this was really relevant). (More details on Google Chrome documentation).
    I'm not sure window.postMessage would help you here.

    If you have static code to execute you could create a Bookmarklet containing the code, then ask your visitors to add it to their bookmarks (bar) and click it to execute changes. But this is not a realistic solution and won't probably fit your need.

    EDIT

    In response to «Please help me understand why that is any more of a security issue» comment.

    Browsers sandboxes code in contexts, each context has its own set of security restrictions and some of them are at risk (mostly) regarding XSS attacks.

    WEB page is the most exposed context to attacks, any browser will execute the code it contains after fetching its URL. This is the ideal target for attacks (such as XSS) because the more people visit an affected website the more people pay the costs. This is why restriction such as Cross-Origin Resource Sharing exist which prevent different frames (with different domains) to access each other documents by default. There are factors that ease attacks, for instance: identified security flaws in open source outdated CMS consisting in not correct escaping of content coming from the database letting tags appear in the page source (which is then executed by browsers…), etc.

    In the "Extension" context, some APIs require the developer to explicitly ask for permissions in the extension's manifest file. Interactions with the current page (active tab) is granted if the ActiveTab permission has been declared. Once you install an extension, you give access to APIs the extension has requested for.

    The developer console context is a particular case. What is executed their ONLY COMES FROM YOU AND WILL ONLY AFFECT YOUR EXPERIENCE. One can guess that risks are quite limited there compared to code in websites source (where there may have injected malicious code using XSS attacks). In other words, only the code you enter in the console will be exectuted there and no code from a WEB page will gain access to the console context.
    You may have experienced browsers warning you about risks when you past code to execute in the console, telling you to do so if and only if you understand what the code will do or at least if you absolutely trust the author/origin of the snippet.

    A (not so) fictional scenario: Access Iframe content from main page. Let say we have a web page containing malicious script. This script could try to identify installed extensions by periodically scanning DOM nodes and look for specific extensions injected content, and ultimately access that content.

    All this reminds me an interesting article for developers.