Secure your React Native Apps before production!

Give security a chance ✌🏼

Madrid

We all know that the weeks before launching an app into production are stressful enough, but do not forget about the vulnerabilities while you finish all the features for the MVP product.

stessed monkey

In this post I'll talk about three common vulnerabilities when it comes to React Native Apps. Code Obfuscation, disabling logs in production and what happens with the API keys of our app, how can we store them safety?

Code Obfuscation 🉐 ️

When deploying your React Native app all the java code is compiled into a DEX file. This file is readable unless you obfuscate your code. Fortunately this can be done quite easily adding a few parameters to our app gradle file!

First things first, we need to activate the obfuscation from the app gradle file of your app. So navigate to [app_name]/android/app/build.gradle and inside the buildTypes section add the following lines:


With the lines minifyEnabled and useProguard, we will activate the minification and obfuscation of the code, but we need to indicate the location of the proguard configuration file so that's why we have added the setProguardFiles directive.

Then we'll need to setup our proguard configuration (proguard-rules.pro) file, in this file we're going to add al the exceptions and rules that proguard will use when obfuscating our code.


This are the recommended rules by the react-native team, most of them are exceptions to core packages that the compiler needs to find during the compilation time, so they can't be obfuscated.

Now, some exceptions:

1.- If your using react-native-config in order to configure different environments in your app. You will need to add the following lines to the end of your proguard-rules.pro file.


Where mypackage should match the package value in your AndroidManifest.xml file.

2.- If your using react-native-firebase in your app. You will need to configure exceptions to the firebase packages in your proguard-rules.pro file. This depends on which firebase packages are you using, so please check the firebase documentation.

Disable Logging in release 📋

We don't want any logs in our application in a release version, cause they may expose some sensible data as parameters sended to https requests, endpoints, etc...

In order to disable the logging, we only need to add a new package to the babel configuration. Babel is the compiler for react native code, with this package added, babel will remove all the logs in our code when compiling a release/production version.

So you can keep your logs when deploying a debug version but keeping the relase version secure!

Disable the logging can be done in two simple steps:

1.- Install the following plugin for babel babel-plugin-transform-no-console by executing the following command:


2.- Add the following configuration lines to your .babelrc file (In case that you didn't have one create the file in the root of your react native project).


3.- If you are using redux-logger for logging the redux calls add the following code to your store in order to not apply this middleware when we are in a release version.


Managing API Keys 🔑 with environment files.

When it comes to production, we don't want to expose any sensible key in our code, that's why they must not be stored as plain text in our code. ¿How can they be managed then?

Well, here is when the magic of the continuous integration (CI) came into play. The best practice is to store the keys as enviromental variables in our CI provider (For example: CircleCI, TravisCI or GitLabCI ), in most of this services these keys can be added as enviromental variables in the configuration pages.

For example, in the case of CircleCI, this means that all the variables we set from the configuration are availiable in the docker images runned for our project in CircleCI. Therefore, we'll only need to use an script that replaces all the enviromental variable references in our environment file for it's actual values. This is where we use envsubst.

envsubst it's command included in the gettext package, that will do precisely that, it will replace all the references to environment variables of a file for it's actual values. Therefore we'll only need to commit our .env.tpl file to our repository and envsubst will be in carge of creating the actual environmental file.

Example:

Imagine that we have the following environmental template file (.env.tpl).


If in out CI config file we setup the following action...


envsubst will generate a .env file replacing all the references for it's actual values, so the CI will be in charge of managing all the API keys for us leaving our app secure.

EXTRA: As React Native doesn't have native support for managing environment variables We'll need to use the following package react-native-config if we want to do so. The package is a little outdated and the configuration can be a little bit messy but it's very useful to be able to use environmental files and managing diferent environments in the app.


So, keep all of this tips in mind when deploying a React Native app into production! Data exposure or API keys exposure can be serious things! And before you know it you may end up as the guy in the gif!