Does anyone know if there is a way to load any external executable javascript from a firefox add-on extension? I looked into scriptloader.loadSubScript, but it appears that it can only load from a local resource.
Any help would be appreciated.
You can always xhr for a file, save the contents to disk, then use scriptloader.loadSubScript with an add-on
this would violate the AMO policies though, so you wouldn't be able to upload the add-on to http://addons.mozilla.org
As #erikvold already pointed out, doing so would be a security hazard AND it also violates AMO rules (because it is a security hazard).
Consider your server gets compromised, or there is a way to MITM the connection retrieving the remote script (TLS bugs anyone :p), or you sell your domain and the new owner decides to ship a script to collect credit card information straight from a user's hard disk...
However, it is possible to run a remote script in an unprivileged environment, much like it would run in a website.
Create a Sandbox. The Sandbox should be unprivileged, e.g. pass an URL in your domain into the constructor.
Retrieve your script, e.g. with XHR.
Evaluate your script in the Sandbox and pull out any data it might have generated for you.
This is essentially what tools like Greasemonkey (executing user scripts) do.
Creating and working with Sandboxes in a secure fashion is hard, and the Sandbox being unprivileged prohibits a lot of use cases, but maybe it will work for your stuff.
Try using Components.utils.import .
Example :
const {Cc,Ci,Cu} = require("chrome");
Cu.import("url/path of the file");
Note :
js file which uses DOM objects like window, navigator, etc. will return error saying "window/navigator is undefined". This is simply because the main.js code does not have access to DOM.
Refer this thread for more information.
Related
I am unable to read clipboard data in Microsoft Edge browser. i am using the below javascript.
if (window.clipboardData && window.clipboardData.getData) { // IE
pastedText = window.clipboardData.getData('Text');
} else if (e.clipboardData && e.clipboardData.getData) { //non-IE
pastedText = e.clipboardData.getData('text/plain');
}
Non of the if/elseif block is executed in Edge. I tried using
e.originalEvent.clipboardData.getData('text/plain');
But I am getting 'Access is denied.' error.
Let me know, if anybody know how to fix this issue.
Edge does not currently support the clipboard api, but it is under consideration and likely to be added in near future.
I do not have edge, but it seems that you are not authorized to access the clipboard data. Is this on a website or are you calling this from within a JavaScript script executed locally?
Make sure the website is in the trusted sites.
See https://w3c.github.io/clipboard-apis/#clipboard-event-interfaces, or more precisely:
12.1 Privacy concerns
Untrusted scripts should not get uncontrolled access to a user's clipboard data. This specification assumes that granting access to the current clipboard data when a user explicitly initiates a paste operation from the user agent's trusted chrome is acceptable. However, implementors must proceed carefully, and as a minimum implement the precautions below:
Objects implementing the DataTransfer interface to return clipboard data must not be available outside the ClipboardEvent event handler.
If a script stores a reference to an object implementing the DataTransfer interface to use from outside the ClipboardEvent event handler, all methods must be no-ops when called outside the expected context.
Implementations must not let scripts create synthetic clipboard events to get access to real clipboard data except if configured to do so.
Implementations should not let scripts call document.execCommand('paste') unless the user has explicitly allowed it.
Implementations may choose to further limit the functionality provided by the DataTransfer interface. For example, an implementation may allow the user to disable this API, or configure which web sites should be granted access to it.
I'm trying to write a Firefox extension which hooks into WebAudio and adds a 'master-gain' to all AudioContexts.
I am trying to do this by overriding the AudioContext constructor in the window namespace. This way I can return a GainNode (which is internally connected to the destination) when the user tries to access destination. It's a hack, but I think it might be useful.
I'm currently struggling at exporting my newAudioContext constructor from the addon script(privileged scope) into the page script (less-privileged).
I tried...
unsafeWindow.AudioContext = cloneInto(newAudioContext,unsafeWindow);
But I still get the original AudioContext in the page script.
I also tried
exportFunction(newAudioContext, unsafeWindow, {defineAs: "AudioContext"});
but that exports it as a function and not as a constructor.
I understand that structured cloning has limitations, but are there any other ways I can override the window.AudioContext from an AddOn?
If you need to run more complex code (e.g. object construction) in the unprivileged context you can simply import a script into the target window (after waiving xrays) through the mozIJSSubScriptLoader.
Any function that needs to call into privileged code can be patched into its prototype from the chrome side after the script has been loaded.
You can do this before DOM parsing - and thus before any content script execution - by listening to the DOMWindowCreated event.
You will have to do this from a frame script, since the addon-sdk's page-mod sandboxes don't have enough privileges to access the script loader.
Keeping interaction with the unsafe window to a minimum, i.e. either running code wholly in the privileged environment with xrays or completely in the untrusted environment with the minimal amount of glue methods between those two seems like good security hygiene anyway.
Of course you should be aware that content code will be able to pick apart and modify any classes you create in content. It is untrusted after all.
I am building an application that simulates user input (command+c and command+v). Before sandboxing it, everything worked fine, but now I am getting these errors from the console:
Firstly, when I fire it up:
5/27/13 1:35:11.980 AM appleeventsd[54]: A sandboxed application with pid 5343, "CopyBoard" checked in with appleeventsd, but its code signature could not be validated ( either because it was corrupt, or could not be read by appleeventsd ) and so it cannot receive AppleEvents targeted by name, bundle id, or signature. Error=ERROR: #100013 { "NSDescription"="SecCodeCopyGuestWithAttributes() returned 100013, -." } (handleMessage()/appleEventsD.cp #1755) com.apple.coreservices.appleevents.peer.0x7fa9b0411260.xpcq
Then, when I try to simulate command+c, I get:
5/27/13 1:52:22.980 AM WindowServer[85]: post_filtered_event_tap_data: Sender is prohibited from synthesizing events
5/27/13 1:52:23.000 AM kernel[0]: Sandbox: sandboxd(6515) deny mach-lookup com.apple.coresymbolicationd
5/27/13 1:52:24.252 AM sandboxd[6515]: ([5343]) CopyBoard(5343) deny hid-control
I'm looking for a solution that would allow me to copy and paste globally in a sandboxed environment. Is it possible that the Accessibility API is a good answer? Has my problem got anything to do with how I'm simulating user input? I'm very confused, thank you very much for helping.
The sandbox is designed to prevent exactly what you seem to be trying - allowing an application to simulate a user is defined as a security issue. If you have a narrow requirement which can be done safely you can submit it to Apple thorough bug reporter as an needed improvement to the sandbox.
The Accessibility API is not supported in general for this reason - no playing with other apps! This did not go down so well with all the developers which used it...
You can use AppleEvents in limited constrained circumstances and with the appropriate entitlements.
You'll probably need to go to developer.apple.com and read all the documents/view videos/etc you can find to see if what you wish is going to be possible.
The only point of hope I can offer you is that the sandbox is a moving target, so you may find you can do more than the above suggests. Go read. Good luck.
The problem: toggle javascript support without restarting firefox (nor resorting to different driver) during cucumber test run.
If Firefox's prefutils were exposed to javascript in a web page, that would make it possible. But it is not the case.
So, is there a plugin that does it? Or is there another way to solve the problem? Or is there a good tutorial (that highlights the exposing bit) on how to make such a plugin?
Edit
On a second thought, how would javascript be of any help once it is disabled? Probably the whole idea is a bit screwed.
I assume that your tests run with normal web content privileges. In that case, they aren't going to be able to affect browser settings such as whether JavaScript is enabled (I assume that's what you mean by "toggle JavaScript support").
I'd implement a simple XPCOM component with a method to turn JS support on and off (by setting the appropriate pref). You can expose it as a JavaScript global property so that your tests can access it. See Expose an XPCOM component to javascript in a web page for more details. Package your component in an extension and make sure it is installed in the Firefox instance where your tests are running.
If you want to access the preferences API directly from your content script, you can add the following prefs to Firefox, either in about:config or by adding the following lines to prefs.js in your profile directory:
user_pref("capability.principal.codebase.p1.granted", "UniversalXPConnect UniversalBrowserRead UniversalBrowserWrite UniversalPreferencesRead UniversalPreferencesWrite UniversalFileRead");
user_pref("capability.principal.codebase.p1.id", "http://www.example.com");
user_pref("capability.principal.codebase.p1.subjectName", "");`
user_pref("signed.applets.codebase_principal_support", true);
Replace www.example.com with the domain that you want to grant the privileges to. Also add this line to your JS code before you call the preferences API:
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
A local file (something loaded from file:///) is allowed to request additional privileges. Normally you would get a prompt asking whether you want to allow access - you can "auto-accept" the prompt by adding the following lines to prefs.js in the Firefox profile:
user_pref("capability.principal.codebase.p0.granted", "UniversalXPConnect");
user_pref("capability.principal.codebase.p0.id", "file://");
user_pref("capability.principal.codebase.p0.subjectName", "");
You page can then do:
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var branch = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
branch.setBoolPref("javascript.enabled", false);
This will definitely work if your page is a local file. Judging by the error message however, you are currently running code from about:blank. It might be that changing capability.principal.codebase.p0.id into about:blank or into moz-safe-about:blank will allow that page to get extended privileges as well but I am not sure.
However, none of this will really help if JavaScript is already disabled and you need to enable it. This can only be solved by writing an extension and adding it to the test profile. JavaScript in Firefox extensions works regardless of this setting.
That means you need Javascript to toggle enabling or disabling Javascript.
function setJavascriptPref(bool) {
prefs = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.setBoolPref("javascript.enabled", bool);
}
I have written a Firefox extension that catches when a particular URL is entered and does some stuff. My main app launches Firefox with this URL. The URL contains sensitive information so I don't want it being stored in the history.
I'm concerned about the case where the extension is not installed. If its not installed and Firefox gets launched with the sensitive URL, it will get stored in history and there's nothing I can do about it. So my idea is to use a bookmarklet.
I will launch Firefox with "javascript:window.location.href='pleaseinstallthisplugin.html'; sensitiveinfo='blahblah'".
If the extension is not installed they will get redirected to a page that tells them to install it and the sensitive info won't get stored in the history. If the extension IS installed it will grab the information in the sensitiveinfo variable and do its thing.
My question is, can the bookmarklet call a method in the extension to pass the sensitive info (and if so, how) or can the extension catch when javascript is being called in the bookmarklet?
How can a bookmarklet and Firefox extension communicate?
p.s. The alternative means of getting around this situation would be for my main app to launch Firefox and communicate with the extension using sockets but I am loath to do that because I've run into too many issues over the years with users with crazy firewalls blocking socket communication. I'd like to do everything without sockets if possible.
As far as I know, bookmarklets can never access chrome files (extensions).
Bookmarklets are executed in the scope of the current document, which is almost always a content document. However, if you are passing it in via the command line, it seems to work:
/Applications/Namoroka.app/Contents/MacOS/firefox-bin javascript:alert\(Components\)
Accessing Components would throw if it was not allowed, but the alert displays the proper object.
You could use unsafeWindow to inject a global. You can add a mere property so that your bookmarklet only needs to detect whether the global is defined or not, but you should know that, as far as I know, there is no way to prohibit sites in a non-bookmarklet context from also sniffing for this same global (since it may be a privacy concern to some that sites can detect whether they are using the extension). I have confirmed in my own add-on which injects a global in a manner similar to that below that it does work in a bookmarklet as well as regular site context.
If you register an nsIObserver, e.g., where content-document-global-created is the topic, and then unwrap the subject, you can inject your global (see this if you need to inject something more sophisticated like an object with methods).
Here is some (untested) code which should do the trick:
var observerService = Cc['#mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
observerService.addObserver({observe: function (subject, topic, data) {
var unsafeWindow = XPCNativeWrapper.unwrap(subject);
unsafeWindow.myGlobal = true;
}}, 'content-document-global-created', false);
See this and this if you want an apparently easier way in an SDK add-on (not sure whether SDK postMessage communication would work as an alternative but with the apparently same concern that this would be exposed to non-bookmarklet contexts (i.e., regular websites) as well).