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());
    }
});

Check-Checker Checks Your Checks

Written by Pete Corey on Jul 27, 2015.

I’ve been shouting about why you should check all of the user provided arguments in your Meteor applications for months now. Working with unchecked arguments can lead to a variety of serious security issues in your application.

But still, I find myself coming into client projects and security assessments where I see developers forgetting to check their arguments!


The audit-argument-checks is a great package designed to get people to check all of their method and publication arguments. Unfortunately, it has its shortcomings.

audit-argument-checks will only tell you that you’re missing check coverage for a method or publication at runtime, when that method or publication is called. The package politely informs you of this missing coverage by throwing an exception and killing the current method or publication.

What’s worse, audit-argument-checks is not a debugOnly package, so these exceptions will continue to be thrown in production releases, potentially breaking your application (arguably for good reason).


Wouldn’t it be great if we could get a report of missing checks at startup, rather than through exceptions at runtime? Now you can! Check out my newly released east5th:check-checker package.

meteor add east5th:check-checker

check-checker was born of my need to quickly get informed about the state of argument checking in an application during a security assessment. It’s built on top of ESLint, and uses static analysis techniques to find all method and publication declarations in a Meteor application. If check is not called on a method or publication argument within the body of the handler, a warning is shown in the server logs.

Imagine you have a file in your Meteor project, example.js, that contains method and publication declarations with unchecked arguments:

if (Meteor.isServer) {
  Meteor.methods({
    foo: function(bar) {
      return MyCollection.find();
    }
  });

  Meteor.publish({
    test: function(rab, oof) {
      SensitiveDocuments.update(rab, oof);
    }
  });
}

After adding check-checker, you’ll see the following warning in your server logs after the application starts:

/example.js:
   Method 'foo' has an unchecked argument: bar
   Publication 'baz' has an unchecked argument: rab
   Publication 'baz' has an unchecked argument: oof

The goal of check-checker is to make it easier for developers to quickly find where they’re lacking check coverage. The faster you can find the chinks in your armor, the faster you can secure your application.

Exploiting findOne to Aggregate Collection Data

Written by Pete Corey on Jul 21, 2015.

After watching Rob Conery’s awesome series of screencasts detailing how to build an eCommerce application using Meteor, I was excited to dig into his code. Along with finding a few other security vulnerabilities, I had fun playing with an interesting way of exploiting a findOne query to aggregate data from a Mongo collection.

To get started, take a look at this getCart method defined in shopping_cart.js:30-32:

getCart : function(userKey){
  return Carts.getCart(userKey);
}

And the corresponding Carts.getCart method in carts.js:

Carts.getCart = function(userKey){
  var cart = Carts.findOne({userKey : userKey});
  ...
  return cart;
};

The first thing you’ll notice (I hope) is that the userKey argument isn’t being checked. Your horror may be tempered, though, when you notice that it’s being passed into a findOne query instead of a find.

What’s the worst thing a hacker could do? Sure, they might get a single random Cart by passing in a query like {$gt: ''}, but it’s not like they can get at our whole collection, right?

… Right?!


Well, it turns out you can easily pull down all data from a collection using a findOne query. Take a look at some code a malicious user could run in their browser’s console to do just that:

var carts = [];
function getCartAndSave(userKeys) {
    Meteor.call('getCart', {$nin: userKeys}, function(e, r) {
        if (e || !r || !r._id) {
            return;
        }
        carts.push(r);
        userKeys.push(r.userKey);
        getCartAndSave(userKeys);
    });
}
getCartAndSave(['']);

And just like that, the entire carts collection has been pulled down to the client. Let’s dig into the code to see what’s going on.

The key here is the $nin query operator. We begin by calling getCart and asking for a Cart who’s userKey is not in ($nin) the array ['']. This will return a random Cart. We push this cart’s userKey onto the array and ask for a Cart who’s userKey is not in that array. This will return another random Cart from the collection that we haven’t yet seen. We repeat this process until there are no more Carts to find, and we’ve aggregated all of the Carts on the client.

Now Mr. Malicious User can take his time perusing your potentially sensitive data.


Like most Meteor security issues, the fix for this is to check your user-provided arguments:

getCart : function(userKey){
  check(userKey, String);
  return Carts.getCart(userKey);
}

Now, a malicious user can’t pass an object into the getCart method. They may only pass a String, and will only be able to find a Cart if they know its userKey.

Never allow users to pass arbitrary data into your queries!