HTML/JavaScript Script Injection Exception - javascript

I tried to write a bookmarklet which depends on another script. For this my bookmarklet includes a function like this:
function load(url, callback) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.async = false;
script.onload = callback;
document.head.appendChild(script);
}
The callback function is called on most pages, but on some pages I get the following exception in the console and the script is not loaded (facebook.com is one example).
Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE)
An example of a bookmarklet:
javascript:function%20load(url,callback){var%20script=document.createElement('script');script.type='text/javascript';script.src=url;script.onload=callback;document.head.appendChild(script);}load('http://code.jquery.com/jquery-1.11.1.min.js',function(){console.log('Loaded');})
I use FireFox 29 on Ubuntu 12.04. If it is executed a "Loaded" should a appear in the console. On the first load an additional access to the resource is visible in the console. But as written above on e.g. facebook.com nothing happens at all. Neither is the script loaded nor is the callback called.

It was quite likely due to XSS from the bookmarklet itself. FF 35.0 doesn't have an error anymore and shows a well formatted message.

Related

How to find which [content] script execute the eval code

Recently In my chrome, every page loads https://s3.amazonaws.com/exthub/e/2/r/US_chrome.js?cached=true and it is really annoying. I want to find which extension added such code snippets. But in the Network panel of Chrome devtools, the Initiator just shown VM***, I could not find which script invoke it even I set some break points in the scripts.
I have a lot of chrome extension, so it was difficult to check echo extension one by one. I also tried to search some keyword like content_scripts,executeScript,amazonaws and so on in %AppData%\..\Local\Google\Chrome\User Data\Default\Extensions, but I still could not find it.
Is there any convenient methods for finding the source script.
The VM*** script is the following.
(() => {
if (document.querySelector('script[data-awssuidacr]') !== null) {
return;
}
const head = document.querySelector('head');
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://s3.amazonaws.com/exthub/e/2/r/US_chrome.js?cached=true';
script.dataset['awssuidacr'] = 'KMyretRSNnBnMx4zVMxXIXOlCwtj9scH';
head.appendChild(script);
})();
#dorian Thanks for your advice. Now I tried to disable the "YouTube Video Downloader", and the scripts did not show up again.
I did not find the extension by searching some keywords was because I forgot the unpacked extension, they are not in the %AppData%\..\Local\Google\Chrome\User Data\Default\Extensions directory. And I go through the code and find the js code was obfuscated.

Object Still Undefined Even within Script Onload

I am writing up a ContentScript for a Chrome Extension. In the script, I want to import a javascript (actually a JS and a CSS) and initiate a class from that script.
To ensure the Javascript is properly loaded, I followed the guidance from several SO posts like this, this and this.
var link = document.createElement( "link" );
document.body.appendChild(link);
link.onload = function(){
console.log("link loaded");
var script = document.createElement('script');
document.body.appendChild(script); //or something of the likes
script.onload = function () {
...
console.log("script loaded");
// somehow ContentTools is undefined even after the script is loaded
editor = ContentTools.EditorApp.get();
editor.init('*[data-editable]', 'data-name');
console.log("all finished")
};
script.src = "https://....min.js";
};
link.href = "https://....min.css";
link.type = "text/css";
link.rel = "stylesheet";
I am assuming that this way of callling ContentTools.Editor at the innermost of the nested onload is a good way of guarantee that the proper CSS and JS dependencies are properly loaded. However, when I run it as a Chrome Extension inside the contentscript, it errors out with Undefined ContentTools as referenceerror but I saw message "link loaded" and "script loaded".
Clearly, ContentTools are loaded and defined (see the screenshot). And if I execute the whole script directly in the console, everything works. Looks like the root cause is only in Chrome Extension content script, somehow the editor = ContentTools... got called before the script is fully loaded.
As it is only an error as a Chrome extension but not in the Console, I am a bit lost here. jQuery related solution is also welcome here.

Can jQuery.getScript show the file as a resource in Chrome Developer Tools?

My code needs to load scripts on demand.
function includeJS(uri) {
return jQuery.getScript(uri);
}
includeJS('/path/to/script.js').always(function() {
// do something after script is loaded
});
The problem, though, is that the JS file will not be available in the Chrome Developer tools like other files that were included statically on the page. Due to this I cannot easily put break points.
Is there an alternative to jQuery.getScript that will also show the script in the Chrome Developer tools with the ability to put break points?
EDIT: Adding solution based on currently accepted answer (I will still consider other solutions, but this seems to work for me)
function includeJS(uri) {
var def = $.Deferred();
var script = document.createElement('script');
script.src = uri;
script.onload = function() {
def.resolve();
}
script.onerror = function() {
def.reject();
}
document.body.appendChild(script);
return def.promise();
}
You can simply append a script tag, and use an onload handler to execute post-load actions. Example: https://jsfiddle.net/0nu2dusu/
var script = document.createElement('script');
script.src = 'my_external_script.js';
script.onload = loadHandler;
document.body.appendChild(script);
You have slightly less control over failed loads than $.getScript offers, but the script does show up in dev tools.
Actually it's always there. Just take a look at an example from the jQuery.getScript() site. Here's how it looks like: http://i.imgur.com/LMFFAag.png.
The problem with .getScript() is that it never caches files requested, so on every call it adds some random string to prevent caching (what also prevents us from debugging code). But there's workaround for that:
Set global .ajax caching (not recommended) before you call .getScript():
$.ajaxSetup({
cache: true
});
Use direct .ajax() call (recommended):
$.ajax({
dataType: "script",
cache: true,
url: url
}
If it's your own script, you can always add a debugger; command anywhere to force browser to enter the debug mode (DevTools must be opened).

JSONP Works on browsing to URL but not on refresh

On a page I have 2 javascripts. The first script (A.js) appends a script to the head of the parent page in order to pass JSONP. The first script then takes the JSONP array data and puts it into an array for the second script to use. When I go to the hard URL everything works fine. If I F5 it doesn't work. If I add an alert to the first script right after the JSONP is done then everything works.
So, I am guessing that when refreshing, for some reason, everything happens much faster and therefore the appending of the script doesn't have a chance to happen and the array never receives the data.
How can I fix this?
Main Page:
<script src="A.js"></script>
<script type="text/javascript">
ArrayValueOnMainPage = ArrayValue.FirstValue
</script>
A.js:
//Fail safe default
ArrayValue = {"FirstValue":["NULL"]};
function initiate(data){
ArrayValue = data;
}
function loadJSONP(url){
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
head.appendChild(script);
}
loadJSONP('/test.json');
test.json:
initiate({"FirstValue":["Hello"]});
On hard browse to URL FirstValue is passed as Hello.
On F5 refresh FirstValue is passed as NULL.

Injected javascript does not execute

I'm trying to write a piece of javascript that integrates a webpage with an external system. Currently, what I have is a very small amount of code that dynamically inserts a script element into the page.
$(document).ready(function() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://example.com/example.php?arg1=1&arg2=2";
document.body.appendChild(script);
});
The JS returned by the external system is a large one-line document.write call which writes a table to the page.
document.write('<table><tr><td>blah</td></tr></table>');
When I inject this script element into the page, I can see it using a DOM inspector, but the script does not appear to execute. If I put the script element into the HTML manually, the javascript executes just fine (so it's not a same origin policy or malformed html error...), but I'd like it to be dynamic.
Any ideas why the javascript isn't executing?
Using document.write after the DOM is ready will replace the contents of the page with whatever it is you're writing.
I suggest using one of the actual DOM manipulation methods if you want to insert anything into a page.
As far as the script not executing, are you positive it's being attached correctly? Have you tried setting a javascript breakpoint on the included script to verify that this is the case?
Try to use this code (it the same use by google for analytics or facebook).
Put it on the bottom of your page ;)
<script type="text/javascript">
(function() {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = '/example.php?arg1=1&arg2=2';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(script, s);
})();
</script>
OR as davidbuzatto suggest, you have to use $.getScript() which is a shorthand $.ajax() function.
$(document).ready(function() {
$.getScript("/example.php?arg1=1&arg2=2", function(data, textStatus, jqxhr) {
console.log(data); //data returned
console.log(textStatus); //success
console.log(jqxhr.status); //200
console.log('Load was performed.');
});
});
Edit :
Seens you have probably a cross-domain restriction, just try to use relative url "/example.php?arg1=1&arg2=2" instead of the full url for the include.
Or if it's not the same web server, use a cross-domain.xml file.
Because you are just including it, not executing. As you are using jQuery, take a look in the $.getScript() function.
http://api.jquery.com/jQuery.getScript/
It will fit your needs. This function is an Ajax function, so take care, because its behavior is asynchronous. Use its callbacks to execute code that is based in the loaded script.
Edit: Felix corrected me about the script execution, but I still think that you may give the function a try.
i think you need to use JSONP to achieve that and using a call back function to append it to body tag
$(document).ready(function() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://example.com/example.php?arg1=1&arg2=2&callback=showit(data)";
document.body.appendChild(script);
});
function showit(data){document.write(data);}
I've always seen this done more like:
document.write('<scr' + 'ipt>---scripthere---' + '</scr' + 'ipt>');
I'm assuming it is for similar reasons. Try that instead of creating a "real" script element.
Why not just stick the JS in a separate window/iframe where it executes and displays the tables correctly, and then pull that table using AJAX to that page?
JQuery AJAX is the easiest to use IMO:
http://api.jquery.com/jQuery.ajax/

Categories