Protecting your Firefox OS App code

One question we get asked quite often about developing web applications using HTML5, CSS3, and JavaScript, is about how to conceal code. Reasons range from preventing cheating, protecting intellectual property, hiding encryption algorithms and others. Since JavaScript is executed on the client side, even on Firefox OS, the users can get access the code if they have the skills and spend the time. But don’t get the wrong idea! Applications on Android, iOS and most mobile platforms can be reverse engineered with effort and the right tools.

We will present some measures that make it harder for copycats to reveal your application’s code. In various degrees they will increase the effort, skills and tools required to get the code.

Compressing your code

This is the starting point for most developers. Compressing your code reduces the file size by removing what the browser doesn’t need to run your application. It starts by stripping comments and unnecessary white space. This is a good first step as comments usually reveal a lot of information on how the code is working.

The next level is shortening names of local variables and functions, the so called mangling. As this removes the meaning on those symbols, it further reduces readability.

More advanced compression tools, like UglifyJS, will actually parse your JavaScript to analyze and transform it. This allows not just renaming local symbols but also rewriting conditions and loops into shorter expressions, joining variable declarations (hoisting) and removing unreachable code. The resulting file is not only smaller and less readable but in many cases also faster.

You can take this one step further with the Google Closure optimizer in Advanced mode. The tool allows settings for all the aforementioned transformations. Advanced mode is the most aggressive and requires greater consideration when used, to ensure that the output runs just as the input. It will rename, inline and even remove functions, properties and variables, so you need to make sure to either reference all symbols correctly or annotate them. The extra work pays off as the result is highly compressed and even gains a performance boost. As an example, let’s see what can happen to this code:

document.onload = function() {
  var shareImage = document.querySelector("#share-image");

  function share() {
    var imgToShare = document.querySelector("#image-to-share");

    if (!imgToShare.naturalWidth) {
      alert("Image failed to load, can't be shared");
      return;
    }

    // Create dummy canvas
    var blobCanvas = document.createElement("canvas");
    blobCanvas.width = imgToShare.width;
    blobCanvas.height = imgToShare.height;

    // Get context and draw image
    var blobCanvasContext = blobCanvas.getContext("2d");
    blobCanvasContext.drawImage(imgToShare, 0, 0);

    // Export to blob and share through a Web Activitiy
    blobCanvas.toBlob(function (blob) {
      var sharingImage = new MozActivity({
        name: "share",
        data: {
          type: "image/*",
          number: 1,
          blobs: [blob]
        }
      });
    });
  };
  shareImage.onclick = share;
};

Once we’ll run this code through Google Closure, the code will look like:

var b=document.querySelector("#share-image"),
c=document.querySelector("#image-to-share");b&&c&&
(b.onclick=function(){if(0

Of course, the further you are writing custom logic, the more the code will be obfuscated, as the tools cannot change names from reserved word, or core functions. There are many tools online, and you can choose the one that fit your need. Most web frameworks offer interchangeable libraries and build steps that bundle and compress your JavaScript sources. For smaller projects your IDE, like Sublime Text, can be extended with packages available.

Using Emscripten

Did you remember that we said JavaScript is interpreted code? Well, you can bend that rule. Mozilla's Emscripten tool compiles C and C++ to JavaScript. The output isn't JavaScript as you know it. It behaves more like native code and manages its own memory (stack and heap) in pre-allocated typed arrays. This reduces garbage collection and makes inspecting the memory harder. The output also benefits from asm.js, a highly optimizable subset of JS, that runs on all modern browsers. If you are moving your app from native to the web you can just convert your existing libraries. But even if that doesn't apply, moving your protected code into a C/C++ library that you compile to JavaScript is the best option to get blazing performance with the added benefits of obfuscation.

Using a web service

Compression and compilation isn't the safest solution as people still have access to your code: it's just a bit harder to understand the logic. On the other side, one technique that moves the code to a place you have more control over is to use a web service. Your secret logic would run as a server-side script that your application will call when needed. Someone might be able to inspect the in- and outgoing data but there is no way they will be able to view your logic without access to your server. The major downside is that this feature will be only available when the user is online.

Let's see a simple example on how you can achieve this with a Firefox OS app, and a Node.js script: let's say we would like to hide our super exceptional fantastic code to do the addition to two numbers. Here is a simple node.js script (the goal is not to teach node.js, but show you a working basic example):

"use strict";
var express = require('express');
var app = express();

// Set up express to parse body
app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart());

// Only one route for web service
app.post('/', function(req, res) {
    // Convert parameters from request body
  var firstNumber = parseInt(req.body.firstNumber, 10);
  var secondNumber = parseInt(req.body.secondNumber, 10);

  if (isNaN(firstNumber) || isNaN(secondNumber)) {
      // Bad request, fail with 400 status
      return req.send(400);
  }

  var result = firstNumber + secondNumber;
  res.send({'result': result});
});

app.listen(8000);

Now in your app, you'll call this script by sending the values you want to add, and the script will return you the result. Of course, users can see the call you make, and the results you'll get, but they won't be able to see the magic behind the hidden function.

"use strict";
var firstNumber = 4;
var secondNumber = 5;

var data = new FormData();
data.append("firstNumber", firstNumber);
data.append("secondNumber", secondNumber);

var xhr = new XMLHttpRequest({mozSystem: true});
xhr.open("POST", "http://fharper-nodejs.nodejitsu.com", true);

xhr.onload = function() {
    // Parse the response and do something with it
    var response = JSON.parse(xhr.response);
    console.log(response.result);
};

xhr.onerror = function() {
    console.log("Magic failed");
};

xhr.send(data);

This code is just showing the web service pattern and not best practices. As any server, it still needs security measures to prevent exploits. Make sure you mask the request and response data by using a secure HTTPS connection. Control client access to your service by checking the Referrer and Origin HTTP headers but don't trust what you see as they can be faked. You can limit replaying request with malicious parameters by using adding a secret time-limited or single-use token. As you can see, having your code in a web service is keeping it off the client but opens different attack vectors you need to consider.

Be proactive, open your code

Of course, the best approach is to open your code: make your application open source, choose the right license, and show to the rest of the world that you were the first to create this piece of art. Choose the technology you want: you will make it harder to copy your code, but there is never a way to hide your idea. You need to be proactive: you need to be one of the best in your domain. Show your expertise, innovate, add features faster than the competitor do, be relevant for your market, and believe in what you do. How many knock offs of Angry Birds can you find on the web or on any marketplace/store? I don't have the exact number, but I can definitely say with a lot of confidence, that it's many! Rovio had an amazing idea, and they were the first to make it a reality: they are always innovating with brand new levels, new games with the characters we like, and more. You, your children, myself, we want to play to the original one, not the copy. Replace Angry Birds with any app or games you like, and you'll understand what I mean.

You have access to an amazing platform that open the web like never before: take advantage of it, build that app you want, and make your idea a reality!

About Harald Kirschner (digitarald)

Harald "digitarald" Kirschner is a Product Manager for Firefox's Developer Experience and Tools – striving to empower creators to code, design & maintain a web that is open and accessible to all. During his 8 years at Mozilla, he has grown his skill set amidst performance, web APIs, mobile, installable web apps, data visualization, and developer outreach projects.

More articles by Harald Kirschner (digitarald)…

About Frédéric Harper

As a Senior Technical Evangelist at Mozilla, Fred shares his passion about the Open Web, and help developers be successful with Firefox OS. Experienced speaker, t-shirts wearer, long-time blogger, passionate hugger, and HTML5 lover, Fred lives in Montréal, and speak Frenglish. Always conscious about the importance of unicorns, and gnomes, you can read about these topics, and other thoughts at outofcomfortzone.net.

More articles by Frédéric Harper…


22 comments

  1. Willy Aguirre

    Is just I am looking for Using a web service =)

    December 5th, 2013 at 09:51

    1. Frédéric Harper

      Happy to help, let us know if you need more information.

      December 5th, 2013 at 10:08

  2. SunboX

    I’m using …

    for JavaScript: npmjs.org/package/closurecompiler
    for CSS: npmjs.org/package/yuicompressor
    for HTML: npmjs.org/package/html-minifier

    December 5th, 2013 at 10:04

    1. Frédéric Harper

      Great packages, thanks for sharing the information.

      December 5th, 2013 at 10:09

  3. Lisa Brewster

    Note that if your app is privileged, the Marketplace app review team still needs to see your unobfuscated code. After submission, instead of waiting for us to ask for it, you can save time by sending your source to app-reviewers@mozilla.com, which is a small team of Mozilla employees and community members who volunteer their time to review apps.

    If you have concerns sharing your code even with this small group, just let us know more about your situation and we’ll work with you on a solution.

    December 5th, 2013 at 13:57

    1. Frédéric Harper

      Exactly, thanks for the addition to the post Lisa.

      December 5th, 2013 at 14:00

    2. SunboX

      Thanks Lisa! I came across this one and thought “damn, couldn’t you tell me this earlier?” ;o)

      December 6th, 2013 at 00:38

    3. Sheldon

      Some collaborator reviewers are developers of other Apps, so It is complicated to protect your code if later you have to send it to other developers.

      I don’t understand yet, why we have to send the source code when in other Markets it is not necessary.

      December 8th, 2013 at 05:19

      1. Andrew Williamson

        As Lisa mentioned, if you have concerns about sharing readable code with our community reviewers who may be involved with other apps, then let us know and discuss a solution.

        We read the source code to check the APIs are being used safely. Its a manual review right now so submitting it is the most efficient option (de-obfuscateing is rarely a good output)

        December 9th, 2013 at 18:29

        1. Luke

          It seems a bit odd to have proprietary web apps running on OSS based phone. I mean, when there is eventually a FirefoxOS-Greasemonkey app, will it not be able to style and tweak these apps, if they are marked proprietary?? And will we have a warning about which apps are non-free?

          December 9th, 2013 at 19:08

          1. Frédéric Harper

            All applications are HTML, CSS, and JavaScript, so you can tweak these applications for now, by debugging with the Web Developer Tools as an example (even the OS applications).

            As for the paid application, you can see it directly in the marketplace app like in this screenshot https://hacks.mozilla.org/wp-content/uploads/2013/12/paidapp.png .

            December 10th, 2013 at 08:04

  4. Brett Zamir

    This is good information for web developers in general as well.

    December 5th, 2013 at 20:09

    1. Frédéric Harper

      Our primary focus was Firefox OS, but since Firefox OS applications are, in fact, web applications, you can apply everything in this article to anything else.

      December 6th, 2013 at 13:45

  5. Luke

    Nice article – It should probably be mentioned that good coding standards can make a lot of difference, in addition to minifying for maximum load-times.

    For example, no minifier can safely combine jQuery chaining, and something like this can be worse for js length, and execution time:

    $(‘#something, .anotherthing’).addClass(‘whatever’)
    $(‘#something, .anotherthing’).attr(‘something’,’something’)
    $(‘#something, .anotherthing’).attr(‘another’,’attr’)

    Also a lot of people don’t like minifiers so much because it has code that the user can’t easily understand, may be considered shady. (Most exploit codes are minified for example) – see https://www.gnu.org/philosophy/javascript-trap.html

    If compiled/minified apps are part of the FirefoxOS store, must the original code be available to the reviewers?

    December 6th, 2013 at 20:52

    1. Frédéric Harper

      Good points, and as Lisa said in the comments’ section: if your application is using privileged API, you need to give the unobfuscated code to the reviewers, so they can do their job (the published code will be the obfuscated one).

      December 7th, 2013 at 05:42

  6. niutech

    You can obfuscate your JS code further by using bananascript.com or jscrambler.com. But the best solution is to share your code with others!

    December 7th, 2013 at 03:57

    1. Frédéric Harper

      Thanks for sharing those other tools.

      December 7th, 2013 at 05:44

  7. Steve

    Helped me a lot recently. Good idea to post it ;) Thanks

    December 7th, 2013 at 22:30

    1. Frédéric Harper

      Glad it helped you Steve!

      December 9th, 2013 at 09:24

  8. Sourav

    Can’t online Javascript beautifiers, like this one http://jsbeautifier.org/ be used to rename the variables back .. though it may not be able to totally decode the code but can provide some help to understand the logic later.

    December 15th, 2013 at 07:35

    1. Frédéric Harper

      As we wrote in the article, it’s a first step to try to protect your code: it will discourage some developers, but we also listed more advanced technique. It’s impossible to rename variables back as there is no way that a tool finds the logic behind the code with obfuscated variable names. The best it can do is to beautify the code (unpack, adding space, aligning code…), but you still have to understand the logic with variables like a, b, and c.

      December 16th, 2013 at 06:24

  9. Sourav

    Hmm. yes thats required by the person who decodes it . Thanks @Frederic

    December 18th, 2013 at 08:16

Comments are closed for this article.