The Ecstasy of Testing

Written by Pete Corey on Aug 18, 2015.

describe("The ecstasy of testing", function() {

You dive in, equipped with nothing more than a creeping dissatisfaction and a passing test suite.

As the darkness of uncertainty begins to envelop you, the shining green light of your passing suite fills you with unbounded confidence. Fearlessly, you make your first refactor. Vast swaths of code fall away before you, subjected to the annals of git history. Intricate towers of loosely coupled components assemble themselves upon the foundations of your assumptions and beliefs.

In your gut, you feel that it’s ready. You hit save. Your waiting tests eagerly devour your creation, but something is wrong. The suite is failing. Exceptions smoulder red with roars of unmet assertions. You realize that you’ve missed an entire set of edge cases. Your assumptions were unfounded, and were it not for the meticulous diligence of your test suite, devastating. Cries of what could have been are drowned out by a torrent of mechanical clicks and clacks as your fingers deftly recover from your oversight.

Once again you set the suite into motion. Between the hushed sounds of your bated breath you can nearly hear the whirring cogs of your test harness as it churns through vast permutations of possibilities and potentialities. Finally, the gears come to rest.

The screen glows green in front of you.

Your tests are passing.

It’s finished.

});

DOS Your Meteor Application With Where

Written by Pete Corey on Aug 10, 2015.

If you’ve read my previous posts, you’ll know that I talk quite a bit about the dangers of not checking your method and publication arguments. These posts usually boil down to the dangers of letting users pass arbitrary data into your collection query objects. These types of vulnerabilities usually take the form of data leakage, or unauthorized data modifications (which are very serious issues), but it’s also possible to completely hang an application with a well-crafted query.

Let’s dig into an example to see how this can happen and what we can do to prevent it!

The Setup

Let’s pretend that you’re building a Meteor application. Within this application you have a very simple method called grabData. It expects you to pass in an ID, and it will return the corresponding item from the Data collection:

Meteor.methods({
  grabData: function(id) {
    return Data.findOne(id);
  }
});

Awesome, our method works! Now imagine what would happen if a malicious user ran the following method call in their browser console:

Meteor.call('grabData', {$where: "d = new Date; do {c = new Date;} while (c - d < 10000);"});

Uh oh… What is this $where operator? What’s all this Date and looping business? And why is my app completely unresponsive?

The Exploit

The $where operator will execute any valid Javascript string on each element in the collection over which you’re running your query. It’s intended use is to run complicated queries that may carry out some business logic on a document before deciding whether to include it in the result set. Unfortunately, $where will execute any Javascript passed into it - including Javascript designed to loop forever.

We were expecting the client to pass an ID into grabData, but our malicious user decided to get more creative. They passed in a selector object with a $where operator designed to spin your Mongo instance’s CPU at 100% for 10 seconds. By pegging the CPU of your Mongo instance (which may or may not be the same CPU used by your Meteor application), the malicious user has essentially DOS’d your application.

Check out a quick demonstration:

This is a particularly nasty vulnerability. In this case, our malicious user was kind enough to free the CPU after 10 seconds. In the real world, an attacker may peg your CPU indefinitely, forcing you to restart your Mongo instance.

The Fix

So how do we avoid this type of “NoSQL injection”? Wherever possible, don’t trust user input, and definitely don’t pass it directly into a collection query. Always check that your user arguments match your expectations, and be especially careful when using the $where operator.

A simple fix to our grabData method may look like this:

Meteor.methods({
  grabData: function(id) {
    check(id, String);
    return Data.findOne(id);
  }
});

You can use my new package, east5th:check-checker to see if you have any unchecked arguments in your application’s publications and methods.

Returning Promises Synchronously

Written by Pete Corey on Aug 3, 2015.

This past week I was working on a Meteor project that made use of a Node.js package that used promises; specifically es6-promises. I often found myself wanting to return results from this package in my Meteor method calls. This meant I had to use some form of Fibers/Futures to transform my asynchronous promises into “synchronous” code.

The usual method of transforming asynchronous code into a synchronous style is to use Meteor’s wrapAsync utility method. wrapAsync works by wrapping your provided function in a future that returns when the callback to your provided asynchronous function is called. Unfortunately, wrapAsync only works with traditional asynchronous methods that take an error-first callback as their last parameter. This means we won’t be able to use it to transform our promises into a synchronous style.

Without being able to use wrapAsync, I found myself writing a lot of code that looked like this:

Meteor.methods({
  lolpromises: function(a) {
    Future = Npm.require('fibers/future');
    var future = new Future();
    returnsPromise().then(function(res) {
      future.return(res);
    }, function(err) {
      future.throw(err);
    });
    return future.wait();
  }
});

Basically, I’m creating a Future, and returning what the value of that future will be from the method. My promise resolve method returns the value to the future, and the reject method throws the rejected value as an exception.


I decided to wrap this functionality into a package: east5th:wrap-promise. Using that package, you can return a promise in a synchronous styling like this:

Meteor.methods({
    lolpromises: function(a) {
        return wrapPromise(returnsPromise());
    }
});

The package is duck-typing the promise’s then interface, so it should work with any promise library that supports that interface. Check out the code if you’re interested.


After talking about this with Dean Radcliffe, I realized that there’s a better, officially supported way to accomplish my goal: Promise.await in the promise Meteor package.

Using the core promise package, our lolpromises method would look like this:

Meteor.methods({
    lolpromises: function(a) {
        return Promise.await(returnsPromise());
    }
});