I've written a small Greasemonkey script to add a couple of hotkeys to YouTube for controlling the volume when the video doesn't necessarily have focus:
// ==UserScript==
// @name Custom Youtube Hotkeys
// @version 1
// @include https://www.youtube.com/watch*
// @grant none
// ==/UserScript==
var customScript_Player = unsafeWindow.document.getElementById("movie_player");
window.onkeypress = function(event) {
//ignore keypress if focused on search bar
if (unsafeWindow.document.activeElement.tagName === "INPUT") { return; }
try {
if (event.keyCode == 120) {
customScript_Player.setVolume(customScript_Player.getVolume() + 5);
} else if (event.keyCode == 122) {
customScript_Player.setVolume(customScript_Player.getVolume() - 5);
}
} catch(err) { console.log(err.message); }
};
However, I'm concerned about the security concerns raised with the use of unsafeWindow. As far as I can tell, it's necessary to execute JavaScript on the page elements, but I'm seeing conflicting information about what security risks it poses.
I've seen a couple of discussions where it's claimed that the only security holes opened by its use come from the APIs Greasemonkey provides which are blocked using @grant none in the script header, and that as long as grant is set to none the page can't do anything it wouldn't be able to normally.
However, the wiki itself makes several warnings about avoiding unsafeWindow and doesn't seem to ever specify its only a problem when using its own API.
Is the above script secure? If not, is there a safer way to inject javascript that can control the page elements?
Thanks!
I'm concerned about the security concerns raised with the use of unsafeWindow.
In GreaseMonkey, userscripts run in content
script context while webpage JavaScript runs in page
context.
The Xray vision separation is made specially to prevent page JavaScript gaining access to privileged functions.
unsafeWindow
creates a bridge between the 2 contexts which if not careful, can expose some of the content
context functions to the page
JavaScript.
Note: In GreaseMokey (& FireMonkey) unsafeWindow
is an alias for window.wrappedJSObject
. Therefore, there is no difference between using either.
TamperMonkey & ViolnetMonkey implementation of unsafeWindow
is different.
In your example code, if you don't need to use any of the GM functions, you can simply inject the whole code into the page
context without the need for unsafeWindow
e.g.
const script = document.createElement('script');
script.textContent = '...code....';
document.body.appendChild(script);
script.remove(); // if you want, makes no difference