Wednesday, April 30, 2014

Culture eats strategy for breakfast - a short goodbye :)

Today is my last day as an official employee at Rapid7, the company I co-founded 14 years ago. While I'll still be involved as a part-time advisor, it's always bittersweet when starting a new chapter. I thought I would share my farewell letter to the company - it's as good a summary as I can make of my philosophy on startups and on the importance of corporate culture.



Fellow Moose,

Fourteen years ago, almost to the day, Tas, Alan and I started Rapid7. It's been an amazing ride - we have accomplished so much in that time and I'm proud to have played a part in this incredible story. I've had the opportunity to work with some pretty amazing people from whom I've learned a great deal. I've learned about what it takes to grow and scale a business, what it takes to succeed, and I've learned a lot about myself. One of the things I've learned is that I am, at my core, a startup guy. I love small companies and small teams, I love starting new things, and it's time for me to get back to my roots. So…tomorrow will be my last day as an official employee of Rapid7.

Someone asked me the other day what it's like to be part of a startup. The best way I can describe it is that it's like a shared delusion; you have to keep the hallucination going, keep everyone dreaming, keep YOURSELF dreaming, until that dream starts to become a reality. Once in a while, someone "wakes up", they fall out of the dream, and we don’t hear from them again. And that's OK - we just keep going.

You know in the cartoon where Wile-E-Coyote runs off the edge of the cliff and keeps running on thin air? It's like that - except you've got a dozen people running beside you. And everyone is responsible for making sure that nobody else looks down.

You start off with just a couple people - not geniuses, just regular folks who have no right to start a company. If you're incredibly lucky, you've got a killer idea, but probably what you've actually got is an idea that's just barely good enough to work. And if you can somehow find the nerve to believe you'll succeed when the odds are overwhelmingly tilted towards failure; if you can stay flexible and keep adapting and making sh*t up until you find out what works; if you can work 10x harder than everyone else so you can outrun your early failures; if you can sustain that belief, that dream state, for long enough…then you have a chance of pulling it off.

That's why the "Who" is so much more important than the "What". That's why culture matters. And that's why I've always said that we're not in the software business. We're not even in the security business. We're in the people business.

When I look back at the last 14 years, there's so much to be proud of. We've built a great team, we've shipped products that help customers, we've closed big deals, we've done acquisitions that took the industry by storm, we've broken record after record, and we've earned the praise and recognition of analysts and the press. Even though we have much more to achieve, we should be really, really proud.

With all of that said, what I'm most proud of is the personal success of the people who have joined this shared delusion we call Rapid7. I've had the great privilege of helping people I hired grow into world-class engineers, sales people, and managers. I've seen them get promoted, earn degrees, obtain US citizenship, get married, buy homes, and start families -- taking advantage of all the opportunities that Rapid7 provides. I will be forever grateful for having been even a small part of that success.

I'm incredibly proud of the team we have today and I'm excited about where Rapid7 is headed. You're all ready for the next phase of growth, adventure, and success. Just remember to keep taking care of each other, and don't look down!

With love,
   Chad

Monday, April 28, 2014

If you lived here, you'd be home now - thoughts on the Internet Explorer 0-day vulnerability


Growing up around Boston, I remember seeing the famous billboards for the Charles River Park apartments: "If You Lived Here, You'd Be Home Now".  These signs were placed strategically, almost sadistically, on Storrow Drive where they were seen every day by the thousands of motorists trapped in rush hour gridlock.  This morning, as IT departments scrambled to react to the Internet Explorer 0day vulnerability, I couldn't help but think about that devilish piece of advertising.

This critical vulnerability in all versions of Internet Explorer was discovered by FireEye "in the wild". When a vulnerability is found being actively exploited like this, there is no time for the vendor to prepare a patch -- the only responsible course of action is to follow the dictates of military journalism: "Maximum disclosure with minimum delay". This resulted in Microsoft publishing its security advisory on a Saturday, while its engineers were still feverishly working on a patch.

Monday morning dawned with no available patch for this issue. The US and UK governments (and most IT departments) published guidance saying to avoid using Internet Explorer until a fix becomes available. Presumably, FireEye's excellent technology can be configured to block this attack, but edge-protection technologies only protect users while they are on the corporate network. Anyone using a laptop from home, a hotel, or a coffee shop is still wide open to attack.

What else can be done at this point, without a patch? A lot, as it turns out! Organizations who have done a good job at deploying Microsoft EMET (Enhanced Mitigation Experience Toolkit) on their desktops are protected in large degree from this 0-day attack. EMET is a free tool that provides system- and application-level control over exploit mitigation settings such as DEP and ASLR. While the exploit does attempt to bypass DEP and ASLR (and possibly EAF mitigation), FireEye confirms that systems with EMET 4.1 and 5.0 were successful in blocking the exploit in the wild.

Situations like this are exactly why Rapid7 features EMET deployment as an integral part of our Desktop Recommended Controls in our ControlsInsight product. You can't get a passing grade in ControlsInsight unless EMET is not only deployed to endpoints, but is also configured correctly and actually running. We don't believe that EMET is a panacea, but we have seen time and time again situations where the first few versions of an exploit are blocked by EMET, giving organizations precious time to obtain and deploy a patch in production. Sometimes, all you need is a couple days -- even a few hours of protection can make a big difference in your ability to react and respond to a new vulnerability.

Too many organizations confuse "vulnerability management" with "patch management". There is a LOT more to successfully managing vulnerabilities than simply playing whack-a-mole with known patches. A good vulnerability management program will include a careful of assessment of key controls such as desktop and server hardening, browser and browser plugin configuration, least-privilege settings, antivirus, and exploit mitigations such as EMET. As with any controls assessment, it's not enough to say "We have antivirus installed" or "We have EMET installed" - you have to validate whether AV is installed, up-to-date, and running.


If you came into work this morning knowing that EMET was deployed and properly configured enterprise-wide (and you could prove it), you probably had a very different set of conversations than everyone else who was scrambling to react to this unpatched vulnerability. In other words "If You Lived Here, You'd Be Home Now." :-)



Tuesday, May 14, 2013

Warm-ups and mobility training for BJJ, Judo, and MMA

As a 30-something desk jockey who dabbles in BJJ, Judo, and MMA, I've had my share of injuries over the years. I thought I would share some helpful tips for recovery and injury prevention that I've learned along the way.

Disclaimer: I'm not a doctor, just a random guy on the Internet who has had his fair share of injuries and has been lucky enough to work with some great doctors to find some things that worked for me.

I was prompted to dash off this quick blog post in part to share some information with my friend +Christofer Hoff,, a fellow BJJ-practicing geezer and fellow security guy who has recently joined the ranks of those of us with neck/back injuries.

On my side, I've got L3/L4 disc degeneration and I've had partial rotator cuff tears in each shoulder at different times. I've been lucky enough to avoid shoulder surgery and by being careful about warm-ups and rehab, I'd say I've recovered 85-90% range-of-motion in my shoulders while avoiding further injury.

The typical BJJ / Judo warmup


I notice many, many BJJ practitioners will extensively warm up their neck, shoulders, hips and legs before practice. The typical instructor-led warm-up you seen in BJJ or Judo involves things like running, "butt-kicks", "high-knees", side-to-side skipping, pushups, "shrimping" drills, shoulder circles, neck rotations, plus forward and backward rolls.

While these are great overall warm-up exercises to get your blood pumping, they don't focus enough on the thoracic spine or the posterior chain, key parts of the "core" that have to work properly if you want to avoid injury.

Thoracic spine

The thoracic spine or "T spine" consists of the middle part of the back which is involved heavily in twisting and trunk rotation, motions which are very important to both striking and grappling. Note that when I talk about "T spine", I'm not just talking about the vertebra and discs but also the soft tissue in this area including the paraspinal muscles, traps, rhomboids and the serratus anterior muscles which help to stabilize the scapula.


While it's pretty common in BJJ to hear about cervical (neck) injuries and lumbar (lower back) injuries, one seldom hears complaints about thoracic (mid-back) injuries. This is because problems in the T spine tend to lead to injuries in other parts of the "kinetic chain", namely the lower back, neck, and shoulders. What follows is my (admittedly amateur) attempt to explain why this happens.

All 3 regions of the spine (cervical, thoracic, and lumbar) are responsible for flexion (bending forward) and extension (bending backward). The T spine is unique because it bears additional responsibility for trunk rotation. If your T spine is limited in its ability to rotate, your body will place rotational stress on the lumbar spine (which isn't really designed to rotate), causing lower back injuries. In these situations, people may focus their efforts on rehabilitating the lumbar region while ignoring the original cause of the injury (poor thoracic mobility).

Likewise, if you sit at a desk most of the day like me, even if you are very active outside the office you will likely end up with poor thoracic mobility, manifesting as slight hunching, rounding of the traps shoulders, and "closing" of the chest. Often times, those with rotator cuff injuries will be led to focus rehab on the shoulder stabilizers without looking into the fact that poor thoracic mobility may be what led to your shoulder injuries in the first place. This is why Michael Boyle lists thoracic spine mobility in the #1 spot on his list of mobility drills that everyone should do, noting:

"The nice thing about t-spine mobility is that almost no one has enough and it's hard to get too much"

Posterior Chain

The posterior chain is the group of muscles on the rear side of the body from the deltoids and traps all the way down through the glutes, hamstrings, and calves.

You hear a lot about knee injuries in BJJ. While some of these knee injuries are inevitably due to awkward take-downs, knee-bars, etc. a fair number of knee injuries in sports are actually caused by poor posterior chain conditioning. Many athletes are "quad dominant", meaning they rely too much on their quad strength without adequately recruiting the glutes and hamstrings -- this is a sure recipe for placing too much stress on the knee leading to injury.

Doing squats, deadlifts, and barbell glute thrusts with proper form will really help to strengthen the posterior chain but will also train your body to recruit the proper muscle groups when needed. If you're already doing squats and deadlifts, the barbell glute thrust or glute bridge, popularized by Brett Contreras, is a great addition to your lifting regimen.

I've taken to showing up early for class (along with the other old guys) and adding the following warm-up exercises to my regimen to make sure the glutes, hamstrings, and lower back are warm enough. You can run through this whole series quickly in less than 5 minutes.

  • Simple trunk rotation for 60 seconds, left and right twists with elbows up. Don't force the range of motion.
  • Bird-dogs (opposite arm/leg): 25 each side
  • Bird-dogs (same side arm/leg, takes some getting used to the balance at first), 25 each side
  • 25 deep "air squats" with proper form, make sure you get your quads down to at least parallel with the floor, remember to press up through the heel like with any squat.
  • T spine openers. I love these - cut to the 2:00 mark at this video to see a decent explanation.
  • Walk-outs with yoga pose (repeat entire sequence 3 times). This video shows a variation, but basically you want to stand straight up, then bend over and walk your hands out to a pushup position (taking at least 10 "steps" with your hands), then repeat the sequence shown in the video (bring right foot to right hand, twist right for 10 seconds, twist left for 10, back to pushup position, bring left leg up, twist left for 10, twist right for 10, then back to pushup, then walk your hands back up). Repeat the sequence 3 times.
  • Glute bridge: lay on your back with your knees bent and feet close to your butt. Bridge up, hold, and then back down. Yeah, it looks like aerobics class - deal with it :)

Taking it to the next level

These warm-ups will really help to prevent injury and boost your performance. If you really want to have big gains in your mobility and posterior chain performance, I'd make the following 4 recommendations:

  • Hit the foam roller every day. Yeah, I know it hurts at first, but if you stay on top of the foam roller (no pun intended) after a couple weeks you'll find it won't hurt as much. Typical foam rollers have a hard time getting into the T spine area, so I'd recommend the Trigger Point myofascial release package, which includes not only a few different sized rollers but also their "quad balls", which are great at getting into the shoulder blades and T spine. It's not cheap at $129 (down from $189) but I find that I use it all the time -- the fact that the small roller fits into my gym bag means I can take it with me wherever I train.
  • Spend one workout a week focusing exclusively on mobility. Pick up the 3-DVD set "The Encyclopedia of Joint Mobility", a stretching and mobility program by Steve Maxwell. Steve is a BJJ black belt and his exercises are very relevant and focused on martial artists.
  • Find a great soft-tissue specialist who specializes in "active release" therapy. If you are in Southern California, I can recommend the great docs at Back To Function, who helped me rehab my shoulders and avoid rotator cuff surgery. If you've never had soft tissue work done before, don't think of it as a nice therapeutic massage: think of excruciating pain, pouring sweat, and cursing at the doctor the whole time. You'll feel great afterwards (this may be due to the endorphins, I'm not sure) but more importantly you'll stay healthy and avoid injury.
  • Extra credit: If you haven't already, pick up a copy of the "Magnificent Mobility" DVD by Eric Cressey and Mike Robertson. This DVD takes a whole-body approach with great focus on the core and posterior chain. There is also the sequel, "Inside-Out: The Ultimate Upper Body Warmup" which focuses, as you might guess, more on the T spine and upper body. They're both great products.

Monday, April 29, 2013

UK likely to outsmart Obama on cyber security? Think again

In the April 26th article for V3 titled "UK government likely to outsmart Obama on cyber security", +Alastair Stevenson opined:
"While the US [cyber security] spending does dwarf that of the UK, I'm still convinced the British government will get more bang for its buck, thanks mainly to its more measured focus on education and collaboration.
Obama is yet to release the full details about where the US money will go, but given the nation's track record when dealing with new threats to its borders or citizens, it's unlikely much of it will reach the country's education system. "

In Stevenson's cursory analysis of U.S. cyber security spending, I believe he has made a number of mistakes. First, he states that "Barack Obama followed suit" in increasing cyber security spending after the U.K. announced its Cyber Strategy in November of 2011. In fact, Obama's focus on cyber security goes back to at least May of 2009, when the White House published its "Cyber Space Policy Review". This 30-page document focuses almost exclusively on cyber security, summarizing the administration's policy and proposing action plans to improve cyber security across both the public and private sectors. Federal funding for cyber security has been increasing steadily year-over-year according to the plans laid out in the policy review.

Stevenson seems to focus exclusively on the increase in cyber security funding within the U.S. Department of Defense including the Air Force and DARPA, while ignoring the significant increases in funding for other cabinet-level agencies, including the Department of Justice, the Department of Homeland Security, and the Department of Commerce (which includes NIST). No wonder, then, why Stevenson doubts that "much of [the funding] will reach the country's education system".

In the U.S., the Department of Defense isn't responsible for cyber security education. That job falls more to NIST and DHS. In my blog post last week, I broke down the NIST cyber security spending and provided an overview of NIST's already significant cyber security mission. Both NIST and DHS play significant roles in cyber security education and collaboration - this has recently expanded to include NIST's National Initiative for Cybersecurity Education (NICE) and the DHS's National Initiative for Cybersecurity Careers and Studies (NICCS).

The U.S. is already years ahead of the U.K. when it comes to public-private cyber security coordination and education. What remains to be seen is which efforts (in both countries) end up being worth the investment of tax payer dollars.

Tuesday, April 23, 2013

United State spending on federal cyber security grows in Obama's new 2014 budget (part 1)

Obama's proposed federal budget for 2014 includes broad cuts to a number of departments and programs, including funding cuts of 34.8% for the Department of Homeland Security, 17.7% for the Department of State, and 8% for the Department of Defense.

Despite these cuts, one area the new budget doesn't skimp on is cyber security. The President has consistently called for increased focus on cyber security across both public and private sectors, declaring "The cyber threat is one of the most serious economic and national security challenges we face as a nation".

This policy is reflected in Obama's 2014 budget, the introduction to which states:
"We must also confront new dangers, like cyber attacks, that threaten our Nation’s infrastructure, businesses, and people. The Budget supports the expansion of Government-wide efforts to counter the full scope of cyber threats, and strengthens our ability to collaborate with State and local governments, our partners overseas, and the private sector to improve our overall cybersecurity."

This blog post series will examine the increases in cyber-security spending across each federal agency in the 2014 budget. We will start with the Department of Commerce.

Department of Commerce

The Department of Commerce will allocate $754M (an increase of $131M from the 2012 enacted level) to the National Institute of Standards and Technology (NIST), a good chunk going towards NIST's cyber security mission:
"This funding will accelerate advances in a variety of important areas, ranging from cybersecurity and smart manufacturing to advanced communications and disaster resilience."

NIST's own 2014 budget request contains more details about their cyber-security spending, including the following increases:


When it comes to R&D and Standards (the first line item above), NIST already has well-established role. NIST is the main agency responsible for approving  cryptographic standards used all over the world, including the Advanced Encryption Standard (AES) and the various secure hashing algorithms we've all come to know and love. Much of the rest of the world takes its cue on approved cryptographic practices from NIST.

In addition to its cryptographic mission, NIST is responsible for developing security standards and policies for government agencies through its use of "Special Publications", including most notably:


I recommend that you browse the complete list of NIST's special publications, as there are some good resources there.

NIST runs the NVD (National Vulnerability Database) and the CSRC (Computer Security Resource Center). More information about NIST's computer security initiatives can be found on the NIST Computer Security Division site.

NIST maintains some technical standards related to security automation and the interoperability of security tools like the ones we develop at Rapid7. This family of related standards includes SCAP (Security Content Automation Protocol), OVAL (Open Vulnerability Assessment Language), and XCCDF (Extensible Configuration Checklist Description Format).

In the next part of this series, we will look at the Department of Defense's proposed increases in cyber-security spending.

Monday, April 22, 2013

Microsoft's EMET 4.0 - a free enterprise security tool for blocking Windows exploits

Last week Microsoft announced their 4.0 beta release of EMET (Enhanced Mitigation Experience Toolkit). If you are responsible for securing Windows systems, you should definitely be looking at this free tool if you haven't already.

EMET is a toolkit provided by Microsoft to configure security controls on Windows systems making it more difficult for attackers to successfully launch exploits. EMET doesn't take the place of antivirus or patch management, but it does provide an important set of safeguards against not only existing exploits, but also against future 0-day exploits which have yet to be developed or released. Even the best signature-based antivirus programs don't do a good job at protecting from 0-days.

EMET allows administrators to exercise fine-grained control over Windows' built-in security features in Windows 7 and higher, including:



While DEP and ASLR have been supported by Microsoft since Windows XP SP2 and Windows Vista (respectively), one of the main weaknesses of this mitigation is that existing applications needed to be recompiled by the developer to "opt-in" to these security controls.  A great benefit of EMET is that it allows administrators to "force" DEP and ASLR onto existing legacy applications.

While there are many exploits out there which bypass DEP and ASLR, it's worth noting that the first versions of these exploits are sometimes thwarted by these controls, which buys you some time for either patches or antivirus detection to become available. There are good reasons why the Australian DSD (Defense Signals Directorate) has included DEP and ASLR on its "Top 35 Mitigations" for two years running.

EMET 3.0 and 3.5 introduced the ability to manage EMET via GPO, putting installation and configuration within reach of the enterprise. EMET 4.0 builds on this feature set and includes some very useful new protections, including:

  • SSL certificate pinning - allows mitigation of "man-in-the-middle" attacks by detecting situations where the Root CA for an SSL certificate has changed from the "pinned" value configured in EMET. For example, you can configure EMET to say "There is only a single trusted root CA that should ever be issuing certificates for acme.com, and if I see a certificate for any FQDN ending in .acme.com from a different CA, report this as a potential man-in-the-middle attack. You can pin the CA for entire domains or for individual certificates. EMET 4.0 beta ships with pinned certificates for login.live.com and login.microsoftonline.com, but administrators can add their own.
  • Enhanced ROP mitigation. There is a never-ending arms race between OS and application developers on the one side and exploit developers on the other side. When a new mitigation technique is developed by Microsoft, clever exploit developers work hard to find ways to bypass the mitigation. In the case of ROP mitigations, EMET 3.5 included some basic ROP mitigations that blocked assembly language "return" calls to memory addresses corresponding to known lists of low-level memory management functions in certain DLLs. This rendered a common exploit technique ineffective. However, exploit developers responded with adjusted techniques to bypass EMET's ROP mitigations, such as returning into the memory management code a few bytes beyond the function prologue. I don't have enough time or space to do this fascinating topic justice, but you can read a good overview of ROP exploit techniques here.

    EMET 4.0 blocks some of these mitigation bypass techniques, which puts the onus back on exploit developers in this cat-and-mouse game. I'm looking forward to the first white paper detailing how the new mitigations can be bypassed.
  • Improved logging. With the new and improved EMET notifier agent, EMET 4.0 does a much better job at logging events to the Windows event log. This opens up the possibility of using a centralized event log monitoring systems such as Microsoft Systems Center Operations Manager (SCOM) 2012 to act as an enterprise-wide early detection system for exploit attempts. Imagine having instantaneous alerting any time EMET blocked an attack on any Windows system across the enterprise.

    One could also use a free tool like event-log-to-syslog to gather event logs centrally, or even something like Splunk (with universal forwarders) if you don't mind breaking the bank.

    Another benefit of centrally logging and analyzing EMET events is it will give you early warning on EMET compatibility problems. Past versions of EMET have been known to cause problems with certain applications, for example I found that the LastPass extension for Chrome needed certain EMET settings disabled in order to run. If you haven't used EMET before in your enterprise, you will definitely want to introduce EMET in a limited rollout before going enterprise-wide via GPO. Note any programs requiring exemption or settings customization and make sure those settings are reflected in the GPO policy.
Update 4/22/2013: +gaten guess was nice enough to point out that ASLR was introduced in Vista, not Windows XP so I clarified my comments above. Many of these controls work poorly or not at all in XP, so it goes without saying that if you're running Windows XP anywhere in your enterprise, EMET should be the least of your worries. :)

Tuesday, April 9, 2013

JavaScript static analysis and syntax validation with Google Closure compiler

A while back, I found myself needing to have automated syntax checking and static analysis for JavaScript code. I found JSLint to be less-than-ideal, even though it has a Maven plugin. JSLint is fairly hard to tune, and it does a poor job at grokking the syntax and constructs from 3rd-party libraries such as jQuery and YUI. JSLint also tends to be noisy and difficult to tune.

I played around with a few different options and ultimately settled on the Google Closure Compiler. This is a JavaScript minifier/optimizer/compiler which also does (of necessity) a good job at syntax validation and error checking.

I ended up writing an Apache Ant task to invoke Closure on parts of the project source tree, excluding known third-party libraries from analysis. I'm reasonably happy with the results, although I'm sure one day this should be migrated to a Grunt task using the Grunt Closure Compiler plugin.

Without further ado, here is the Ant task definition. Hopefully the in-line comments make the usage pretty clear -- let me know if you find this useful or if you have any questions! Note that this task definition assumes that the Closure compiler JAR file is located in the ant lib directory.

<!--
   <timed-audit-task> is a reusable macro to run a specific audit tool against the source code,
   storing its output under @{audit-output-dir}. The output directory will be deleted and recreated
   prior to running the audit tool. Some basic logging and timing statements are added for clarity
   and profiling.

   To skip the running of a specific tool, the person invoking ant can specifiy -Daudit-skip-<toolname>,
   where <toolname> is the value passed in to the @{audit-task-name} parameter. By convention this should
   be the short name of the tool, for example "findbugs", "checkstyle", or "pmd". Thus, invoking ant with
   -Daudit-skip-findbugs=1 will cause the findbugs audit tool to be skipped. The actual value of the defined
   property is irrelevant.
-->

<macrodef name="timed-audit-task">
   <attribute name="audit-task-name"/>
   <attribute name="audit-output-dir"/>
   <element name="auditTaskBody"/>
   <sequential>
      <if>
         <not><isset property="audit-skip-@{audit-task-name}"/></not>
         <then>
            <echo>Running @{audit-task-name} on ${ant.project.name}</echo>
            <stopwatch name="audit.timer.@{audit-task-name}" action="start"/>
            <delete dir="@{audit-output-dir}"/>
            <mkdir dir="@{audit-output-dir}"/>
            <auditTaskBody/>
            <echo>Finished running @{audit-task-name} on ${ant.project.name}, see @{audit-output-dir}</echo>
            <stopwatch name="audit.timer.@{audit-task-name}" action="total"/>
         </then>
         <else>
            <echo>Skipping @{audit-task-name} because the "audit-skip-@{audit-task-name}" property is set</echo>
         </else>
      </if>
   </sequential>
</macrodef>


<target name="audit-js" description="Runs source code auditing tools for JavaScript">
        <!--
            JavaScript auditing with Google closure
            Warnings flags are defined at http://code.google.com/p/closure-compiler/wiki/Warnings
            The order of parsing JS files is somewhat important here. You should try to pass
            filenames in the rough order they would be parsed by a browser visiting your site or application.

            We use Google's provided "extern" annotated version of jQuery 1.9 to provide additional
            strict error checking. See https://code.google.com/p/closure-compiler/source/browse/contrib/externs/jquery-1.9.js for more information.

            Best place to find documentation on command-line options for the compiler is
            https://code.google.com/p/closure-compiler/source/browse/src/com/google/javascript/jscomp/CommandLineRunner.java
          -->
         <sequential>
            <!-- Exclude known 3rd party scripts from analysis by filename or path -->
            <selector id="audit.js.3rdparty.selector">
               <or>
                  <filename name="scripts/jquery/jquery-*.js"/>
                  <filename name="scripts/yui/**/*.js"/>
               </or>
            </selector>

            <path id="audit.js.3rdparty.path">
               <fileset dir="${source.dir}/html/scripts">
                  <selector refid="audit.js.3rdparty.selector"/>
               </fileset>
            </path>

            <!-- Include our JS source code to be analyzed, excluding 3rd-party stuff defined above -->
            <path id="audit.js.source.path">
               <fileset dir="${source.dir}/html/scripts">
                  <and>
                     <filename name="**/*.js"/>
                     <not>
                        <selector refid="audit.js.3rdparty.selector"/>
                     </not>
                  </and>
               </fileset>
            </path>

            <!-- Pipe compiler output to /dev/null in a platform-sensitive way -->
            <condition property="dev.null" value="NUL" else="/dev/null">
               <os family="windows"/>
            </condition>

            <pathconvert pathsep=" " property="closure.args" refid="audit.js.source.path"/>
            <timed-audit-task audit-task-name="closure-js" audit-output-dir="${closure.dir}">
               <auditTaskBody>
                  <java jar="${ant.home}/lib/closure-compiler.jar" output="${dev.null}" error="${closure.dir}/closure-warnings.txt" fork="true">
                     <arg value="--jscomp_warning=checkRegExp"/>
                     <arg value="--jscomp_off=checkTypes"/>
                     <arg value="--jscomp_off=nonStandardJsDocs"/>
                     <arg value="--jscomp_warning=internetExplorerChecks"/>
                     <arg value="--jscomp_warning=invalidCasts"/>
                     <arg value="--jscomp_off=externsValidation"/>
                     <arg value="--process_jquery_primitives"/>
                     <arg value="--js"/>
                     <arg line="${closure.args}"/>
                  </java>
               </auditTaskBody>
            </timed-audit-task>
         </sequential>
</target>