1

I have express application in nodejs:

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

My js files which go the browser are in /public folder. I want to obfuscate them automatically in runtime, so it'd be hard to read them in the browser. Is it possible to tune this app setup somehow?

Stepan Yakovenko
  • 8,670
  • 28
  • 113
  • 206
  • 5
    Why are you trying to obfuscate the code in the first place? If you're that worried about someone reading it (which they will find out what it does anyway) then you probably shouldn't be sending it to the browser. – mscdex Nov 28 '14 at 20:02
  • It should execute in the browser, but should not be user-readable. This is what is obfuscation. – Stepan Yakovenko Nov 28 '14 at 22:03

6 Answers6

7

Don't obfuscate at runtime. Create a build step which obfuscates your code and serve the obfuscated code in production.

Install UglifyJS:

npm install -g uglify-js

Then you can run the following command to obfuscate your code:

uglifyjs < src/script.js > dist/script.js

Alternatively, install grunt and the uglify plugin:

npm install -g grunt-cli

npm install --save-dev grunt grunt-contrib-uglify

Create a file called "Gruntfile" in the root of your project with the following contents:

'use strict';
module.exports = function (grunt) {
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.initConfig({
        uglify: {
            all: {
                files: {
                    'public/scripts.js': 'src/**/*.js'
                }
            }
        }
    });
    grunt.registerTask('default', ['uglify']);
};

Run grunt from anywhere in your project to obfuscate your code. Update the index.html file in public/ with a <script src="scripts.js"></script> to load the obfuscated, concatenated scripts.

If order matters, list your scripts in order:

files: {
    'public/scripts.js': [
        'src/1.js',
        'src/3.js',
        'src/2.js'
    ]
}
Jackson
  • 9,188
  • 6
  • 52
  • 77
  • i need runtime obfuscation – Stepan Yakovenko Dec 01 '14 at 10:59
  • 6
    That's stupid. Most obfuscators are really slow, and your visitors aren't going to wait for your code to be minified server-side or client-side on every GET. And if you do it client-side, it's pointless, because anyone can pull up the network tab and examine the body of the HTTP request that delivered the script before it was obfuscated. – Jackson Dec 01 '14 at 21:15
  • Is caching forbidden? – Stepan Yakovenko Dec 01 '14 at 22:31
  • You could cache runtime-obfuscated scripts, but at least one of your users is still going to wait for it. No one ever has to wait if you obfuscate the script pre-deployment. – Jackson Dec 02 '14 at 00:26
  • So how can I connect uglify to nodejs in runtime? This was my initial question. – Stepan Yakovenko Dec 02 '14 at 00:51
  • 4
    I refuse to help you do something so stupid. Find someone else who doesn't care about your users. – Jackson Dec 02 '14 at 01:41
  • uglify has plenty of example on how to run it sync or async. you put a string in and one comes out, so it should be easy to fit into your workflow. – dandavis Dec 06 '14 at 00:15
  • @Jackson is going hard in the paint – RadleyMith Dec 07 '14 at 16:53
5

So, you can't actually keep a user from reading your javascript when it's sent to the browser. You can make it very hard, but a determined user will always be able to transform it to something readable through a combination of automated tools and manual labor.

In short, there's no DRM for JavaScript (or any code, for that matter). If you want to protect the intellectual property in your scripts, put a copyright notice on them. If you think someone stole them, talk to a lawyer.

It's certainly worthwhile to minify your JavaScripts, but the only reason, in my opinion, to obfuscate them is because your stupid boss told you to.

If you want to obfuscate it, check out the answer to this question: How can I obfuscate (protect) JavaScript?

Note that obfuscation is rather expensive, so you really don't want to do it at runtime. You should simply apply it to your javascripts when they change using a build tool like grunt or bower (personally I prefer grunt). These systems have plugins like this to perform the obfuscation.

Community
  • 1
  • 1
jjm
  • 6,028
  • 2
  • 24
  • 27
  • How are you going to deobfuscate this: http://discogscounter.getfreehosting.co.uk/js-noalnum_com.php ??? – Stepan Yakovenko Nov 30 '14 at 23:50
  • 2
    @stiv: that code doesn't even run, but older copies of firefox will turn a function's toString() code into a parsed representation (without comments), so it might very well reduce that down to more basic terms... – dandavis Dec 06 '14 at 00:11
2

You can use UglifyJs in your node application and do what you need using its API. Check out their documentation for further details.

Example from Unglify docs

var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;

var orig_code = "... JS code here";
var ast = jsp.parse(orig_code); // parse code and get the initial AST
ast = pro.ast_mangle(ast); // get a new AST with mangled names
ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
var final_code = pro.gen_code(ast); // compressed code here

P.S. People noting that it is slow and blah blah are of course all correct, but hey, if you need it here it is, I just don't understand why judge and post opinions in response to a clear question.

Dmitry Matveev
  • 5,320
  • 1
  • 32
  • 43
1

My tips are easily bypassed, but without be careful, we can be trapped. And it is only client part, not nodejs part.

Only live view of the page

You can replace or remove script tag with javascript for hide this in live view of the page. But if you watch directly the network, you can see easily the javascript file/code.

<div id="RemoveMe0">
    <script type="text/javascript">
        //This code it is hidden to live view.
        var my_var = 5 + 5;

        $('#RemoveMe0').remove();
        //or document.getElementById("RemoveMe0").innerHTML = "";
    </script>
</div>

For include javascript :

<div id="RemoveMe1">
    <script type="text/javascript" src="Javascript/MyJS.js"></script>
    <script>
        //Your include it is hidden to live view.
        $('#RemoveMe1').remove();
    </script>
</div>

Only direct view

Put your files in an HTML file (myfile.js to myfile.html), like this on a direct view you can execute a javascript function.

function Hello() {
    alert("Hello");
}
Hello();
//<script>document.body.innerHTML = "";</script>

Conclusion :

For this tip, rename file or use .htaccess. And like first tip, if you watching the network you see full file.


Or minize/parse your JS

You can use tool like this :

Community
  • 1
  • 1
user2226755
  • 12,494
  • 5
  • 50
  • 73
1

You can obfuscate the code using command line utility, such as this:

app.use('/javascripts',function(req,res,next){
    if (process.env.OBFUSCATE != 1){
        next();
    }
    var cmd = "java -jar ./gcc/compiler.jar ./public/javascripts" + req.url;// + "> ./tmp" + req.url + ".tmp";
    exec(cmd,function (error, stdout, stderr){
        res.write(stdout);
        res.end();
        if(error !== null){
            console.log('exec error: ' + error);
        }
    });
});
0

I see you are using express and EJS. What I do is create another folder called jsobf that holds the obfucated files. Basically duplicate all your js files with the same name if you want.

In EJS you can do if else check in your ejs files like this :

<% if (process.env.NODE_ENV === "production") { %>
    <script src="/jsobf/myjavascriptfile-prod.js"></script>
<% } else { %>
    <script src="/js/myjavascriptfile-dev.js"></script>
<% } %>

At the top of the file where you do app.listen.. declare you a global variable:

const isProduction = true;

app.listen(PORT, function () {

    if(isProduction){
        process.env.NODE_ENV = 'production';
    }

});

Then all you need to do before you deploy your code is manually obfuscate your code at a site like obfuscator.io

In your dev branch set the isProduction to false and in production branch to true. This way when you are developing everything is taken care of for you.

This may not be the cleanest solution but it works perfectly fine for me if you dont care to obfuscate manually before production deploys.

exceptionsAreBad
  • 573
  • 2
  • 5
  • 17