Skip to content

Greasemonkey and Security: Attempting to Summarize What You Need to Know (Part 1 of 3)

As one might expect when I am unable to access the web as often, the inspiration for what I write about in this entry comes from something that I have read that was not in an electronic form. As I have mentioned previously on this blog, I have taken time to rediscover why I have purchased information that is in the form of ink on processed tree carcasses. And one such book that I had been reading is one that no one who reads this blog should be surprised I own. It is one that likely occupies the bookshelves of many Greasemonkey coders. This book, titled “Greasemonkey Hacks” that was written by Mark Pilgrim and published by O’Reilly Media, contains much information on what can be done with Greasemonkey, the source code to Greasemonkey scripts, and explanations of the source code. It is a book that anyone serious about writing Greasemonkey scripts should at least consider reading.

As one might imagine, much of the information in the book is only useful when one has access to a computer, so that one can work with the example scripts that are there in the book. This book seems to have been designed specifically to be one that would be on a computer desk, likely left open to the last section that a coder using it found interesting. However, there is some information in this book that can be read without finding there to be any need for access to a computer at the time that information is being read. And one of these “hacks” in the book that can be read with no need to have a computer nearby is one that I would say stands out as one of the most important ones in the book. In fact, one may go as far as to say that this hack is one that should be read by anyone serious about writing Greasemonkey scripts that make use of what Greasemonkey has to offer. And it is likely for this reason that this hack titled “Avoid Common Pitfalls” is freely available online as an article on the O’Reilly Network. And that article on O’ReillyNet is actually titled “Avoid Common Pitfalls in Greasemonkey: How the History of Greasemonkey Security Affects You Now.” And here I write about why the latter part of that title is still appropriate.

I had been meaning to write about the security issues that Greasemonkey has and has previously had for some time. In particular, I considered it important to focus on the issue of “cookie stealing” scripts that are discussed here. However, it was only after I read that previously mentioned section of that previously mentioned book that I decided that it would be best to make the topic of Greasemonkey and security the next topic of discussion on this blog. I was going to simply write about what was written by Mark Pilgrim then, and why it is relevant even two and a half years after it was published. And in one of those coincidences that sometimes occur as I prepare to write an entry to this blog, a new version of Greasemonkey was released that addresses publicly disclosed security issues that have similarities to issues mentioned in Pilgrim’s article.

As you may know if you have read Pilgrim’s article, there was a time that Greasemonkey had some very serious security-related issues. In the article, issues that it had that did not seem to be considered when Greasemonkey was first written are mentioned. The issue of “trusting the remote page” on which the scripts are run is primarily noted in it. Remote pages could have been designed to take advantage of issues that can occur when Greasemonkey scripts are run. It was in this article that it was described how in Greasemonkey 0.3, a combination of security flaws could have led to remote pages reading files stored on a user’s hard drive, then the forwarding of the contents of those files to any location on the web. In addition, it was said that the possibility of the remote page redefining the DOM functions used by scripts to work with web pages did not seem to be considered when earlier versions of Greasemonkey were first released. Therefore, another possibility of the remote page running code to interfere with Greasemonkey scripts existed then, and this was an even more serious issue considering that the code in Greasemonkey scripts could have been captured by the remote page. With information on the scripts that were being run, it could have been determined which DOM functions were being used by the script that could be redefined to run code to interfere with the script.

Then in the article, after these security issues are mentioned, the way in which Greasemonkey was updated in version 0.5 to address these issues is noted. No longer did <script> tags get injected into the page in this version to lead to DOMNodeInserted events. Therefore, the remote page could no longer use these events to tell if a Greasemonkey script was injected into the page. And Greasemonkey’s API functions (such as GM_xmlhttpRequest) that allow functionality beyond what JavaScript allows were no longer defined as children of the global window object to make these API functions accessible to remote pages. And by addressing this issue, remote pages could no longer capture a reference to the GM_xmlhttpRequest function to send any data it could gather to any location on the web. Therefore, the issue of circumvention of the same-origin policy that JavaScript has as a security feature was addressed. In addition, the window and document objects were redefined as XPCNativeWrappers, so Greasemonkey would not work directly with objects that could have their methods redefined by the remote page. Instead, when a function call needed to be made, it could be made knowing that the function could not have been modified by the remote page in an attempt to run arbitrary code. Functions would not run arbitrary code, and objects returned by the function calls were also XPCNativeWrappers, and thus, could not have their functions or properties redefined by the remote page.

In addition, it is said in Pilgrim’s article that there are no easy ways around some issues. One of these issues for which no suitable workarounds exist involves the use of the window and document objects. The unsafeWindow and unsafeDocument variables, which are respectively references to the actual window and document objects, are mentioned. It seems the reason these two variables exist in Greasemonkey is because some JavaScript functions on remote pages may need references to the window or document objects as parameters, and these functions would not accept XPCNativeWrapper objects as parameters. Any Greasemonkey script that tries to use functions or properties of the unsafeWindow or unsafeDocument objects should not be considered secure, as remote pages could redefine these functions and properties. And it is for this reason that it is said in the article that use of the watch function, which requires use of the unsafeWindow variable, is considered unsafe in Greasemonkey scripts, as remote page code could redefine this function.

The article by Pilgrim also mentions how past security fixes can lead to common pitfalls when writing Greasemonkey scripts, as JavaScript code that would usually be expected to run properly may not work in the context of a Greasemonkey script. By having Greasemonkey scripts run in what is known as a sandbox, and by working with XPCNativeWrapper objects, some common ways of writing JavaScript code will not work in a Greasemonkey script. There may be more than one way to code a solution to a problem in JavaScript, and it is important to know that there are fewer ways of approaching these problems when writing the JavaScript in Greasemonkey scripts. And so it is important to know the limitations on how the JavaScript in a Greasemonkey script can be written. So when JavaScript that is implemented properly according to reference guides on JavaScript does not work in a Greasemonkey script, the answer to why it does not work may be found in Pilgrim’s article. However, this article may not actually be the best reference guide for times when JavaScript that seems to be properly written does not work in a Greasemonkey script.

One might think that an article written years ago may be outdated. And in some ways, Pilgrim’s article does not seem to be as accurate as it may previously have been. In fact, I recently came across a set of notes by Brian Donovan titled “Greasemonkey Pitfalls 2007” in which it is said that some of the pitfalls mentioned in Pilgrim’s article are not actually valid pitfalls. In Donovan’s notes, there are links to pages with information on each pitfall, and these pages have links to Greasemonkey scripts that are designed to work with those pages. Each of those scripts contain JavaScript code that was said in Pilgrim’s article to not work in the context of a Greasemonkey script. However, after running these scripts on the pages of Donovan’s site, one will see that it appears to be true that some of these pitfalls do not appear to be valid. Other pitfalls, however, do appear to be valid, and it is important for Greasemonkey coders to keep this fact in mind. Pilgrim’s article might not be as accurate as it previously was. Still, it can be considered a good starting point for Greasemonkey coders as they look for information on which ways of writing the JavaScript in Greasemonkey scripts will not work. And it also serves as a guide that describes to Greasemonkey coders why these restrictions on how the JavaScript can be written in these scripts exist.

Indeed, this article was published quite a while ago, and thus there was much time for many to read it. Therefore, many of those reading this post may have already read this article that I am summarizing. However, if giving this summary of this article leads to greater knowledge among Greasemonkey coders of what was written there, and if it leads to more of them reading the article, it will have been worth it for me to write this summary of the article. I think it is quite important that as many Greasemonkey coders as possible read what Pilgrim wrote, and I do not consider the material he wrote as confusing as Pilgrim says it is. It can be good to know about the security issues that Greasemonkey has had before, although what may be considered the main reason it is important is its listing of common pitfalls that result from solutions to Greasemonkey’s past security issues. Still, security issues from the past should be considered relevant, and one reason these past issues matter ties in with the more recent security issues Greasemonkey has had.

These most recent security issues that Greasemonkey has had reminded me of what was said in Pilgrim’s article. These issues involve the unsafeWindow and unsafeDocument objects and Greasemonkey’s API functions, all of which are mentioned in the article. In this software update, a number of scripts that use these objects and these API functions are affected, and will not work with the new version. Previously, to address the much more serious security-related issues Greasemonkey had in version 0.3, many more scripts did not work with it until later versions of it were released. Greasemonkey’s most recent security issues may be considered much less serious than the security-related issues it had before, but these issues should be mentioned. The way in which Greasemonkey scripts are to be written is affected once again. And although the way they must be written is affected to a much lesser extent than before, there are now more of these pitfalls of which Greasemonkey coders must be aware.

This newest version of Greasemonkey, version 0.7.20080121.0, is being mentioned here on this blog weeks after it was actually released. One might think I should have made it a priority to write about this new version sooner. However, I consider this entry that is mostly a summary of an important article the most important entry that I have written to this blog so far. Therefore, I wanted this summary to be as well-written as possible, and so I took much time to try to ensure that it was well-written. In fact, Pilgrim’s article can be considered something of a summary, as it does not list all security fixes that were made to Greasemonkey. For example, scripts are no longer allowed to access URLs starting with “file://” to prevent scripts from accessing local files, and that is not mentioned in Pilgrim’s article. This entry may be considered a summary of a summary, and Pilgrim’s article may only be considered a starting point when reading about security issues. I would also suggest referring to information on security on the GreaseSpot wiki when one has questions about Greasemonkey security. And the security issues addressed by the newest version of Greasemonkey will be covered in the next in this series of entries on Greasemonkey and security. And it will hopefully be published before it becomes too outdated for me to write about this new version.