Blog
February 23rd, 2009
With jQuery 1.3.2 out the door I've been looking for more ways to profile and optimize jQuery.
Previously I did a survey of jQuery-using sites to figure out which selectors they were using. This led to the construction of the new Sizzle Selector Engine which targeted those selectors for improvement.
Additionally, I constructed a deep profiling plugin for jQuery which helped to spot methods that were taking a long time to run in live jQuery sites. This helped bring about the improvements in jQuery 1.2.6, 1.3, and 1.3.2.
What do we tackle next? A good place to start would be to tackle optimizing methods that are obviously inefficient - but how do we determine that? One way would be to measure the number of function calls that occur every time a method is run. Firebug provides this information in its profiling data (along with how long it takes to run each method). Unfortunately it's very clunky to manually type out code, check the results in the console, and determine if they're bad or if they've changed. If only there was a way to progamatically get at those numbers.
FireUnit Profiling Methods
Yesterday I did some work to make getting at the profiling data possible, adding two new methods to FireUnit.
fireunit.getProfile();
Run this method after you've run console.profile(); and console.profileEnd(); to get a full dump of the profiling information. For example, given the following profile run:
You'll get the following JavaScript object returned from fireunit.getProfile():
{
"time": 8.443,
"calls": 611,
"data":[
{
"name":"makeArray()",
"calls":1,
"percent":23.58,
"ownTime":1.991,
"time":1.991,
"avgTime":1.991,
"minTime":1.991,
"maxTime":1.991,
"fileName":"jquery.js (line 2059)"
},
// etc.
]}
fireunit.profile( fn );
The second method added to FireUnit provides an easy way to execute and profile a single function. Roughly, this method starts the profiler, executes the function, stops the profiler, and then returns the results from getProfile(). Additionally, it watches for any exceptions that might be thrown and makes sure that the profiler is cleanly turned off anyway (a frequent frustration of mine).
You would use it like this:
fireunit.profile(function(){
document.getElementsByClassName("foo");
});
How To Use
First, you'll need to be sure to have the latest copy of FireUnit installed. I've built a copy of the latest code, into an extension, if you wish to install it:
When running it you'll need to make sure that:
- Both the Console and Script tabs are enabled in Firebug
- That the 'extensions.firebug.throttleMessages' property in 'about:config' is set to 'false'.
The Results
I put up a test page so that I could quickly run through some jQuery methods to see how they stacked up.
Here are the results of running against jQuery 1.3.2 ("Method" is the jQuery method that was called, with the specified arguments, "Calls" is the number of function calls that occurred when executing the method, "Big-O" is a very rough Big-O Notation for the function calls):
| Method |
Calls |
Big-O |
| .addClass("test"); |
542 |
6n |
| .addClass("test"); |
592 |
6n |
| .removeClass("test"); |
754 |
8n |
| .removeClass("test"); |
610 |
6n |
| .css("color", "red"); |
495 |
5n |
| .css({color: "red", border: "1px solid red"}); |
887 |
9n |
| .remove(); |
23772 |
2n+n2 |
| .append("<p>test</p>"); |
307 |
3n |
.append("<p>test</p><p>test</p> <p>test</p><p>test</p><p>test</p>"); |
319 |
3n |
| .show(); |
394 |
4n |
| .hide(); |
394 |
4n |
| .html("<p>test</p>"); |
28759 |
3n+n2 |
| .empty(); |
28452 |
3n+n2 |
| .is("div"); |
110 |
|
| .filter("div"); |
216 |
2n |
| .find("div"); |
1564 |
16n |
We can immediately see, by looking at the big-O notation, that most jQuery methods execute at least one function for every element that they have to operate against. addClass runs about 6 functions per element, filter runs about 2, and 'is' runs only 1.
We can see the problematic functions sticking out like a massive sore thumb: .remove(), .empty(), and .html() - they all run over n2 function calls, which is a huge issue. (These numbers are all large for a simple reason: .html() uses .empty(), .empty() uses .remove(), and .remove() is obviously inefficient.) While function calls do not, necessarily, indicate slow code (a lot of jQuery's internal functions are pretty lightweight) it is very likely to indicate inefficiently-written code.
I poked around the code for a little bit and realized that .remove() could be dramatically simplified. I filed a ticket and landed a patch which resulted in these much-improved numbers:
| Method |
Calls |
Big-O |
| .remove(); |
298 |
3n |
| .html("<p>test</p>"); |
507 |
5n |
| .empty(); |
200 |
2n |
I'm really excited by this new tool. Automating the process of code profiling opens up whole avenues of exploration. Even using nothing more than the above tool I can immediately see room for improving just about every jQuery method.
It's also be very interesting to have this running in some sort of continuous integration setting, to catch any egregious regressions - but I'll leave that for another day.
Tags: fireunit, firebug, javascript, jquery
46 Comments on 'JavaScript Function Call Profiling'
December 18th, 2008
In my work with the Firebug team over the past couple months I've been working with Jan Odvarko on a way to provide some form of unit testing that we can build off of. The result of my work is a new Firefox/Firebug extension called FireUnit.
FireUnit provides a simple JavaScript API for doing simple test logging and viewing within a new tab of Firebug.
For example, here's some of the API that you can use (we're starting with the basics and looking to expand with more methods, later).
// Simple true-like/false-like testing
fireunit.
ok( true,
"I'm going to pass!" );
fireunit.
ok( false,
"I'm going to fail!" );
// Compare two strings - shows a diff of the
// results if they're different
fireunit.compare(
"The lazy fox jumped over the log.",
"The lazy brown fox jumped the log.",
"Are these two strings the same?"
);
// Compare a string using a regular expression
fireunit.reCompare(
/The .* fox jumped the log./,
"The lazy brown fox jumped the log.",
"Compare a string using a RegExp."
);
// Display the total results
fireunit.testDone();
The results will appear in a 'Test' tab in Firebug (which must be installed in order for Fireunit to work). Each of the results can be expanded to show additional information including a full stack trace of where the test ran and a comparison with a diff.
FireUnit also provides a couple methods for simulating native browser events:
// You can also simulate browser events
var input = document.getElementsByTagName("input")[0];
fireunit.mouseDown( input );
fireunit.click( input );
fireunit.focus( input );
fireunit.key( input, "a" );
And a way of running a batch of test files (each of which would contain a number of individual tests).
// Or run multiple pages of tests:
fireunit.
runTests("test2.html",
"test3.html");
// Place at the end of every test file in order to continue
fireunit.testDone();
We've been using this test runner to run a number of Firebug tests, especially ones that are network based.
Depending on the suite it's pretty easy to adapt existing test suites to display their results in FireUnit.
Running the jQuery selector test suite that has the following snippet added:
if ( typeof fireunit === "object" ) {
QUnit.log = fireunit.ok;
QUnit.done = fireunit.testDone;
}
Yields the following results (which are completely navigable):
If you want to get started using FireUnit you can head on over to the Fireunit.org site and download the latest extension.
You can also grab the source off of the repository on Github.
Jan has also written a blog post detailing a little bit more about what we're using FireUnit for in the Firebug Working Group.
This is still a very early release of our work - there's obviously a ton of room left to grow - so feedback is expected and appreciated.
Tags: extension, firefox, firebug, javascript, testing
44 Comments on 'FireUnit: JavaScript Unit Testing Extension'
August 25th, 2008
The final version of Firebug 1.2 has been released. The release should be up on the Mozilla Add-ons site today, but it's also up on GetFirebug.com right now.
John J Barton and Jan Odvarko put a ton of work into this release (you may have noticed the rapid-fire series of beta releases last week - just trying to smooth out the rough edges).
There have been a number of improvements made (not to mention countless bug fixes). Some of the major points of this release include:
Firefox 3 support.
If you've been using the Firebug 1.2 betas you're already on top of this. Now is a good time to verify the version of Firebug that you're using. Go to Tools > Add-ons in Firefox and see what version of Firebug you're running. If it's anything other than 1.2.0bX (where X is a number 1-15) you'll need to forcefully go to the above Firebug URLs and install the new version (the auto-update isn't working for older versions). The most common report of Firebug problems has been related to running Firebug 1.1 in Firefox 3 - which is a mess (hence Firebug 1.2).
Quality Improvements.
The Script panel (the JavaScript debugger), the Net panel (network monitoring), and Console panel have all seen considerable updates. They're all much more performant and have a huge number of bug fixes.
Specifically the Console panel has seen a number of security improvements. We'll be discussing the specific nature of these changes once everyone has had enough time to upgrade to Firebug 1.2.
A list of all the bug fixes can be found in the full release notes.
Selective Panel Enablement.
This is the most drastic UI change of the release. It's also a, seemingly, bizarre addition to the extension. When you now click Firebug for a site you'll encounter an interface that looks something like this:
Some back story is needed in order to explain why the extension is now set up in this manner. These three panels (Console, Script, Net) have the potential to incur a great deal of overhead into any web sites that utilizes them. There are two pain points, in particular: The Mozilla JavaScript debugger and network monitoring.
The Mozilla JavaScript debugger is used in two ways in Firebug: First it is used in the Script panel (to debug JavaScript code, naturally), second it is used to figure out where JavaScript errors are coming from in the console. Network monitoring is, naturally, used for the Net panel.
Here's the important point: The Mozilla JavaScript debugger and network monitoring are both global to Firefox not localized to a single window or tab. This means that when you enable a panel, such as the script panel, it will turn on the JavaScript debugger for all JavaScript code in Firefox.
Rob Campbell has run some initial numbers and has found that, simply, enabling the script panel anywhere in the browser immediately slows down all JavaScript execution by 25% - for all JavaScript on all tabs in the browser.
We don't have solid numbers on the networking monitoring overhead yet but we imagine it to be much less, although still occurring on a global all-tabs scale which isn't desirable.
The important question here is: What is being done to stop this?
First, it must become necessary to not incur any overhead when using the console panel. This is a ubiquitous part of Firebug and any global overhead presented by it must be removed. This can be done but not without some internal API changes to how Firefox handles and reports error messages. We hope to have something introduced in an upcoming version of Firefox so that we can compensate appropriately in Firebug.
Second, the JavaScript debugger must be improved. A number of bugs have been filed on this subject and we hope that some of them will make their way into upcoming versions of Firefox (Firebug will be able to immediately improve when that happens). Specializing the debugger to only work against a single tab at a time may not be possible (based upon how Firefox works, internally) but if it is that will be an immediate benefit. Of course, any performance improvements to the debugger will always be helpful.
Finally, the overhead of network monitoring (if there really is that much - we haven't run performance analysis her yet) needs to be diminished in any way possible.
All of these things are points that the new Mozilla Firebug team is trying to tackle for the upcoming Firebug 1.3 release.
Who enabled me?
Taking in to consideration the above performance points (namely the fact that enabling the Console, Script, or Net panels have the potential to incur a global overhead on all browser tabs) a feature was added to help you minimize your use of the panels in errant tabs.
If you position your mouse over the Firebug icon, in the Firefox tray, a tooltip will pop up telling you two things: The version of Firebug that you're using and which tabs have some Firebug panels enabled in them.
It should be noted that the Firebug will be a gray color if no tabs currently have a Firebug panel enabled at all.
Using the above tooltip you can now go in and selectively disable any panel usage that you are no longer utilizing.
Suspend/Resume Firebug.
Of course, when using the above tooltip (or seeing that the Firebug icon is lit up), you'll just want to suspend all use of Firebug panels straight out without having to poke-around each individual tab.
A new Suspend/Resume menu option has been added that will suspend/resume all active panels. This is a one-click way to keep Firebug in check.
So what's next for Firebug? I discussed some of the performance auditing that we were doing recently and that will be continuing.
Specifically, however, we plan on releasing some minor updates to Firebug 1.2 to quell bugs and improve performance (there will likely be a 1.2.1 release coming soon).
As I mentioned before, Firebug 1.3 is going to be all about performance, quality, and testing. Firebug is the de facto tool for web developers and we need to make sure that its quality does not wane and that we tackle performance head-on (with the eventual goal of having a seamless web development experience).
Tags: firebug, mozilla
53 Comments on 'Firebug 1.2 Released'
August 12th, 2008
Firebug 1.2 final is set to be released sometime within the next week or two which means that our goals for Firebug 1.3 need to be pretty clear at this point. Last week the Firebug Working Group convened at Google to discuss the goals for the upcoming release. In taking a step back and looking at what was most important one thing was quite obvious: The stability and performance of Firebug needs to be improved.
Unfortunately we're in a very difficult situation. There are, approximately, three developers who've done any sort of serious bug fixing on the internals of Firebug. One is John J. Barton (of IBM - primarily responsible for the 1.1 and 1.2 release of Firebug) and the other is Jan Odvarko (of Mozilla - part of the new Firebug team). Unfortunately the primary source of information lies in Joe Hewitt (the original creator of Firebug), who is quite incommunicado these days.
There are a few areas in which we (and, specifically, the Mozilla Firebug team) need to work in order to gain a solid footing.
Improve the knowledge of Firebug that we have.
Right now information about Firebug internals are quite limited. Not only does there need to be some serious overviews of what's there but inline documentation needs to be improved as well. It can be incredibly hard to hack your way around some aspects of the code base, especially when it isn't obvious how something works.
We're going to be working two-fold in this area: To start Rob Campbell and I will be working on some Firebug extensions in order to get a better feel for the code base - and secondly we will, as we go, write up tutorials and documentation for what we find.
Jan has already written up an excellent series of tutorials that explain how to construct Firebug extensions. They're, already, quite valuable.
Build a runnable set of test cases to prevent regressions.
The unit testing (or, really, any testing) situation in Firebug is quite abysmal. Features have gotten accidentally removed from releases simply because they weren't immediately apparent that they existed. We need to make sure of two things: 1) That existing features don't break or get accidentally removed and 2) That a good enough coverage of the internals is in place to support future development.
Since there is a considerable amount of traffic through the code base (developers contributing patches, multiple developers handling different modules - all over some 35,000 lines of JavaScript code) some form of diligence needs to be provided in order to prevent errors from slipping through.
Track the state of Firebug performance.
There's, effectively, no picture of how Firebug is currently performing (or, more accurately, hindering performance) in Firefox. If we want to improve the quality of the code we have to have a clear picture of which areas are problematic. This is one area in which Mozilla's resources can be especially beneficial.
In Mozilla there is a system called Talos which is used to create builds of Firefox (for all the various branches - right now we're testing Firefox 2, Firefox 3, and Firefox 3.1) and run them against sets of performance tests. The tests consist of page rendering performance, CPU usage tracking, memory usage tracking, JavaScript performance, browser start-up time, graphics rendering, and on and on.
A sample chart - showing page loading performance on Windows XP (a ton more can be found here):
We want to create some builds of Firefox that have Firebug on in various states. For example: Firebug installed (but disabled), Firebug enabled, Firebug with console enabled, Firebug with debugger enabled, Firebug with network monitoring enabled, etc. With all these permutations we'll be able to get an exact number for how much overhead current Firebug code is providing and where we can start to make necessary improvements.
Audit and Improve.
Finally, once we have some documentation about the structure, a test suite running, and nightly performance numbers being generated we can really start to dig in and make improvements. It's going to be slow-going at first but laying this groundwork will make for an effective use of our time (increasing the likelihood that other people will be able to help contribute to the codebase, as well). If we can have a stable and fast Firebug 1.3 ready in time for Firefox 3.1 (which is due out this fall/winter) then I feel like we will have made some good headway and started to serve our purpose well.
Tags: firebug, mozilla
14 Comments on 'Tracking Firebug Performance'
July 17th, 2008
I've got a mini-announcement. Starting this week about half of my time at Mozilla is going to be spent driving the direction of the brand-new Mozilla Firebug team. I'm, understandably, quite excited about this proposition. Like all web developers I've found Firebug to be an invaluable tool for web development.
We have a great team forming - I'm going to be joined by:
We're in a very primordial stage right now - we're meeting at the Firefox Summit at the end of the month and again at the beginning of August for the Firebug Working Group. We'll be setting some major goals for post-Firebug 1.2 development. I highly suspect that we'll be doing some exploratory Firebug extension development as well.
In the meantime we'll be hanging out in the Firebug IRC channel, which can be found here:
Server: irc.mozilla.org
Room: #firebug
We're going to love to hear any suggestions for feature development - I'm sure you've got tons of ideas - and we do as well. I'm quite excited about all of this. Here's to a bright Firebug future!
Tags: firebug, firefox, mozilla
75 Comments on 'Firebuggin''
July 1st, 2008
Like every web developer I've spent a lot of time using the Firebug extension to Firefox in my day-to-day development. I've found it interesting to see how my development methodologies have changed with access to that tool.
Unsurprisingly, my personal development style mirrors much of the general web dev public. But what I find most interesting is to try and track trends in web development that Firebug has single-handedly revolutionized.
Firebug Advances
Performance Profiling
Prior to Firebug there was only rudimentary analysis of JavaScript performance (using tricks like injecting timers and computing the difference). Firebug brought us the ability to analyze all function calls during a period of execution, see how they each affected each other and, probably most important, see the difference in the sub-millisecond range.
Previously none of these techniques were possible with pure-JavaScript techniques - having the ability to tap into the JavaScript engine (which Firebug does) is fundamentally important to getting good analysis.
You can see an immediate interest, by JavaScript library authors, in the performance of their code bases around the time of Firebug's introduction of profiling.
Console logging with object introspection
Logging statements has always been possible with JavaScript (and, most infamously, with the alert() function) however Firebug gave us something significant: The ability to click and introspect into logged objects. This includes the ability to click DOM nodes (and see their properties and methods) and even normal objects (like Arrays or Object literals).
Firebug has to maintain a lot references to point to where these objects exist - and it wouldn't be possible in pure-JavaScript without introducing an excessive number of memory leaks.
Current Styles / CSS Rules
There had existed some tools for examining the current CSS style values of a DOM element (such as its dimensions and positioning) but Firebug brought a whole new level of inspection: The ability to see which stylesheet rules were introducing specific styling on an element. Not to mention the ability to edit the rules in-line (along with disabling them outright).
This level of inspection completely overhauled Web Design - and has been able to detach many web designers from their IDE-of-choice into a more agnostic view of CSS design. Absolutely the biggest short-coming of this feature is its inability to work cross-browser (although, that argument can certainly be used for most Firebug features).
Network Performance
Firebug's network tab gave developers the ability to see - in very real terms - two things: 1) How long a resource was taking to load and 2) How the loading of that resource was blocking the loading of other resources. #2 is especially important, seeing that the execution of JavaScript blocks other actions from occurring can be an eye-opening experience to most developers. Or even seeing how a slow-loading stat tracking script can prevent the further display of the page.
XMLHttpRequest Inspection
While XMLHttpRequest use existed prior to the existence of Firebug it was horribly hard to debug - it was rarely obvious where errors were occurring - on the client-side? on the server-side? in the transmission? The ability to see how the requests occurred - and very importantly - how long they took (and even how frequently they occurred!) has done much to improve the overall quality of Ajax use on web pages.
JavaScript Debugging
I would've said that JavaScript Debugging was a piece of that equation, as well, however Venkman definitely lead the way, in that respect (and has been a de-facto debugger for quite some time).
I'd argue that these trends wouldn't be where they are right now if it weren't for Firebug - and that tools are the primary reason for a development strategy's success. As a corollary look at the relative success of web standards - I'd argue that adherence to HTML or CSS wouldn't be where it is today without the tools to verify a page's compliance.
How to Improve
The question now becomes: What are the next set of tools that Firebug can introduce that will revolutionize its respective areas of development?
I'd like to propose a couple, possible, areas of interest:
JavaScript Library Analysis
As it stands Firebug's JavaScript function analysis is, perhaps, too finely-grained to provide help in many instances - especially when the use of JavaScript libraries is at play. For example, when using jQuery, you're generally more concerned with finding out how fast, or slow, a particular method is - or a selector - not the performance of all the individual internal methods of jQuery.
I began some of this analysis with my Deep Profiling jQuery Apps experiment but that's really only a test. Smart integration of JavaScript library knowledge into Firebug can provide significant details about how your code should be performing.
Visual Performance Profiling
Application performance profiling is rather clumsy right now, we have a number of disparate resources (network performance, rendering performance, script performance) that we need to mentally merge to create a full picture of what's happening. To counter this I'd like to propose a way of visually viewing how components of a site affect its overall performance. Perhaps a way to break things down like this:
- Header: 300ms: 20ms Transmission + 20ms Parsing + 60ms CSS + 200ms JavaScript
- Google Ad: [BLOCKING RENDERING] 600ms: 20ms Transmission + 20ms Parsing + 20ms CSS + 240ms JavaScript + 300ms Frame Loading
- Sidebar: 400ms: 40ms Transmission + 40ms Parsing + 80ms CSS + 240ms JavaScript
The YSlow Firebug plugin already provides some level of analysis on your site - but it's much more holistic (giving you generic tips for files and pieces of code). Whereas a more specific approach would be greatly appreciated.
Ajax Improvements
We currently have the ability to view XMLHttpRequests as they occur, which is great, but some additions could be made that would serve to be quite helpful, such as:
- The ability to manipulate a request and re-submit it. If you're attempting to see how different inputs will affect your site, this would be a great way to play back requests or see how they can be best improved.
- Right now Firebug only lets you know the basic textual output that's coming from the server-side. Having it be able to tell you if incoming XML, JSON, or even HTML is syntactically correct (and even being able to navigate the resulting structures - as the browser would see them) would be a huge boon. As it stands it can be quite frustrating to receive a slightly-malformed response from a server and be stuck trying to figure out what's going wrong.
- Better JSON/JSONP integration is essential. There are a large number of Ajax requests being done through dynamic script tag injection - and those are completely unmonitored by Firebug's XMLHttpRequest tracking. Being able to see what requests and responses look like - and where errors may be occurring - would be immensely useful.
Rendering Performance Analysis
While we have fantastic tools for digging in to the performance of JavaScript - CSS is a complete unknown. How much overhead do our stylesheets provide? How many elements does this CSS rule affect? Does this rule cause a costly reflow to occur? and how many times? How long does it take to render a particular portion of a page? Would changing the structure of my page help to improved perceived rendering speed?
Virtually all of these questions are un-answered and we need a tool to help provide a solid response.
Security Analysis
Security is one area that has seen virtually no attention in the respect of user tools. Most developers have no idea how secure their web site is or how vulnerable it may be to attacks. There needs to be easily-accessible tools for testing:
- SQL Injection attacks
- XSS Injection
- Susceptibility to Spoofing (Data Encryption)
At the very least. The problem here is that while these tools will be incredibly useful for developers to improve their web sites - it'll also encourage malicious behavior. Although, arguably, those that wish to be malicious already have the tools to do so.
Standards Integration
Inline support for analyzing the standards-compliance of a page. Being able to see notes next to specific elements, attributes, CSS rules, etc. that show information on how they don't comply with particular standards - or even how they could be improved to match standards.
This includes inline strictness warnings for JavaScript (produced by the JavaScript engine).
I think that compliance should go a step further, as well, and look to provide information on Microformat and RDFa compliance - pointing out specific errors and helping sites to become better formatted.
Finally - RSS and Atom standards compliance. Notifying a developer that their site's RSS/Atom feed is malformed would allow them to immediately make a more compliant feed (a common area of mistakes).
Internet Explorer Support
The final, and perhaps most difficult, item that should occur would be a port of Firebug over to Internet Explorer. Both Safari and Opera have web developer tools integrated into their browsers - however Internet Explorer still consumes a majority market share and there's no good tools in sight. (I, personally, use CompanionJS but it's still a far cry from the full suite of utilities that Firebug provides - especially in the realm of DOM/CSS.)
This could probably be remedied if there was a really good pure-JavaScript Firebug (although the overhead associated with many of Firebug's features would lead to an astronomically-sized implementation). The current "Firebug Lite" is something of a joke - only vaguely functioning in modern browsers.
Not only do I want to see Firebug improve - it's imperative that Firebug continue to improve, for the sake of web developers everywhere. If it simply stalls and works into a stasis of bug fixes then web developers will be stuck with the current set of tools for quite some time. While other browsers are improving at a rapid pace, it'll still be quite some time before they are able to match the current feature-set of Firebug.
Since so much of web development ecosystem is currently linked to the health of a single tool advances have to be made now and they have to be made quickly in order for the web to flourish and survive as a development medium.
Tags: development, firefox, firebug, javascript, css, programming
41 Comments on 'Powering a Web Revolution'
February 1st, 2008
The Google Caja team has put forward a fantastic document on JavaScript-based injection attacks. This is a fascinating subject and one that receives little attention (but will, undoubtedly, receive more in the upcoming months and years as JavaScript receives more attention).
In their document they detail an injection attack against a SQL database (an obvious example with parallels to existing database injections). However there is another class of problems that are particularly problematic: HTML injection, by browser extensions, allowing web-based content to access privileged code in the browser.
There's a specific example from early last year where a vulnerability was discovered in Firebug, using this very attack vector. (This hasn't been an issue in a long time - I've waited to post these details until the issue had long passed.)
The details:
The vulnerability noticed in a post on GNUCITIZEN related to the escaping of object property names in Firebug. For example, you could run the following code:
console.log({'<script>alert("bing!")</script>':'exploit'})
and it would pop up an alert.
Normally, this wouldn't be a huge concern (nothing more than a bug) - but the script that was executed had all the privileges of the normal browser (for example, to be able to read and delete files).
I was notified about this issue at about 4:36pm (EST), read through the details, tried the exploit, and then set about creating a patch. At 5:32pm I fixed the particular exploit and had a patch ready. At that time I set about trying to find other instances where this exploit could also work.
How the exploit works
Firebug has some very-cool DOM creation code embedded in it. One of the fundamental differences between it and normal DOM creation code is that it creates a serialized string of HTML as output, instead of a series of DOM objects. This means that .innerHTML can be used to inject the HTML (which is blazingly fast).
The published exploit occurred in such a case where a string was being put into this DOM-serialization code, but was not having its HTML characters escaped (in reps.js):
OBJECTLINK(
SPAN({class: "objectTitle"}, "$object|getTitle"),
FOR("prop", "$object|propIterator",
" $prop.name=", // The un-escaped variable
SPAN({class: "objectPropValue"}, "$prop.value|cropString|escapeHTML")
)
)
The fix was simple, just changing the line in question to the following:
" $prop.name|escapeHTML=",
It was at this point that I started to dig around the rest of the Firebug code base, looking for more escaping exploits. At this point Joe published Firebug 1.02 (at about 5:47pm) before I could get any of my patches to him. Looking through the changes that he made, he fixed the exact line that I mentioned before - solving the published exploit.
After some more reading I found another exploit relating to the first one. If you click the serialized version of the (exploited) object in Firebug, it would open up the DOM inspector pane, and execute the un-escaped code.
This second exploit was found in dom.js (which runs the DOM inspection pane):
TR({class: "memberRow $member.open $member.type\\Row", $hasChildren: "$member.hasChildren",
level: "$member.level"},
TD({class: "memberLabelCell", style: "padding-left: $member.indent\\px"},
DIV({class: "memberLabel $member.type\\Label"}, "$member.name") // un-escaped variable
),
TD({class: "memberValueCell"},
TAG("$member.tag", {object: "$member.value"})
)
);
That was another quick patch:
DIV({class: "memberLabel $member.type\\Label"}, "$member.name|escapeHTML")
I notified Joe at about 6:30pm (and pointed out other interesting bits of code) and he set out to see if he could find another set of exploits, as well. Before the evening was over, he was able to find one other loophole in the XMLHttpRequest spying code, and resolve it. It was at this point that he packaged up and distributed Firebug 1.03 at about 7pm, incorporating the three different escaping vulnerabilities that we were able to locate. Later on he provided a systemic fix to the whole escaping issue which has solved future injection problems.
I found the whole experience to be very exciting, and fun; getting a fix out was the top priority, and that was definitely achieved. However, knowing how and why these types of attacks can happen is important to JavaScript development, as a whole. I'm really glad that the Caja team is doing good work in getting the word out.
Tags: javascript, security, firebug
4 Comments on 'JavaScript-Based Injection Attacks'
April 5th, 2007
Note: A series of vulnerabilities were discovered and fixed in Firebug last night - it is very important that you upgrade your installation of Firebug immediately.
How to upgrade:
- Go to Tools > Add-ons and look for Firebug. If the version listed is anything but 1.03, then you'll need to upgrade.
- Click the Firebug entry in Add-ons and click the "Find updates" button below. An entry for Firebug 1.03 should show up. Install it and restart Firefox.
Within 24 hours all Firebug users will be receiving the upgrade - and it will be installed the next time they restart their browser. Regardless, it's important to get this fix installed right away.
Tags: tools, javascript, firefox, mozilla, firebug
4 Comments on 'Firebug 0-day Vulnerability'
·
« Previous entries