Being a responsible adult means dealing with tasks we'd rather avoid but know are essential. From tidying up that catch-all kitchen drawer to visiting relatives during the holidays, it's part of the routine.

Similarly, in the life of a responsible software developer, there are equally crucial but often overlooked responsibilities – like testing and addressing security issues. We might understand their importance but don't always give them the attention they deserve.

Hopefully, after reading this blog post you will want to take better care of your software’s security posture!

A quick introduction to cyber security

Cyber security is a subject as broad as software development itself since every branch of software development faces different security threats. Network security, viruses, hacking, phishing, ransomware, botnets… The list goes on and on. 

However, there is one systemic division pertaining to every type of cyber security work, namely the blue team, the red team, and the purple team. This basic division will help you understand what to expect from a blog post, a podcast episode, etc.

Blue team

Blue team means defensive security. Topics related to the blue team include network administration or software architecture focusing on security. I know “defensive security” sounds a lot like “security security,” but there’s good reason to make the distinction from “offensive security,” aka the red team.

Red team

Red teamers are ethical hackers, professional pentesters or social engineers. They are always the attacking side whose aim is to break through cyber security controls.

Purple team

The purple team is a creative mix of blue and red - as you might expect if you’ve ever mixed paint as a kindergartener. It’s a team taking on the role of the red and blue teams.

Writing in blue, red, and purple

A blue team article might talk about the newest security patches for Linux servers, or about the newest security patches to a popular npm library. A red team article might be a walkthrough for website pentesting, or an account of social engineering feats. The article you are currently reading is a purple team article, as we will employ offensive techniques to be better defenders.

Reverse engineering

Have you ever looked at a piece of technology and wondered how it works? If you have, that’s the first step into reverse engineering. This broad term can describe anything from taking apart your iRobot, to work done by Google’s Project Zero. By the way, Project Zero was able to analyze the functionality of a famous surveillance tool called Pegasus.

Let’s narrow down this topic to reverse engineering of mobile apps. Even working full time on creating mobile apps, they may seem inaccessible for analysis. I write my JS code, I run a command in my terminal to build the app, and I’m presented with an `apk` and `.ipa` files. These files can’t be installed directly on any phone, as apps on regular phones can be installed ONLY through the Play Store and App Store. So is it possible to reverse engineer and analyze a mobile app? It surely is!

The first step in checking how an app was built is using another app called LibChecker. Thanks to LibChecker, you will discover what languages and libraries were used to build any given app. If you were a bad guy - or in cyber security terms, a “threat actor” - you might use this knowledge to search for security vulnerabilities in this app. But you aren’t, are you? So let’s just poke around without causing any harm. 

In order to actually see the files included in an app, you can use, for example APKMirror, APKCombo or APKPure. These are examples of websites where you can find `.apk` files ready for download. And what is `apk`? It’s just a fancy way of packaging and compressing files. 

Once you’ve downloaded an `apk` (e.g. this apk from a very old app I created), you can change the file extension from `.apk` to `.zip` and unzip it. Voila! All the files are magically visible.

folder with multiple files and folders, including XML configuration files, assets and others

You may notice no React Native folder and no `.js` files. However, if you look inside the assets folder you should see the following:

folder with files including index.android.bundle

Files named “index” look quite familiar for React and React Native devs. All right, let’s look inside:

unreadable block of code

At first sight, this looks like gibberish, but at closer inspection, you may notice familiar words, like `var` or `METRO.` This is a compressed JS file. For it to be humanly readable, we need to beautify it. There are different ways to accomplish this, one is using your IDE, and another would be to use online beautifiers. 

My favorite way of inspecting this code is also the most fun way. You start by creating an HTML file where you import this `index.android.bundle` file:

<script src="./index.android.bundle"></script> //save as index.html

Then open this HTML file in your browser. You will see a blank page. But if you inspect it…

chrome inspector, sources tab, looking inside index.android.bundle file

…you will see beautified and readable JS code!

You are now free to look around the functions, the hooks, the context or the variables. 

Other ways to get to JS code are described in detail in a Security Queens’ blog post. The author says that analyzing React Native apps built with Hermes requires using additional tools. I have used the hermes-dec tool with success and I can happily recommend it.

If you prefer to play around with iOS apps, the route is slightly bumpy, but very interesting nonetheless. A great resource to start is this GitHub repo.

There is much more digging that we can do: we could search for strings (strings like API_KEY), we could try to get to the database, and we could try to defeat authorization. For example, did you know that a misconfigured DB on Firebase can lead to some catastrophic breaches? You can learn more about it from a very interesting case study of a Donald Daters app.

Summary

I hope you feel a thrill of excitement and terror at this point. NO app is safe. Just because it takes a few more steps to look at your code than just clicking “inspect” on a website, does not mean your code is inscrutable. 

What can you do about it? I’m happy you asked that question! Learning about reverse engineering gives you a good idea of what an attacker might do, so you have a bigger chance to defend your app and your users against those scary “threat actors.” I hope next time you’re working on an app, you will keep this blog post in mind. Let’s create some safe(r) apps!

Insights

Learn more about Security

cover

Dec 17Podcast

A (Secure) Christmas Carol: The Story of Npmezer Scrooge

A holiday story about npm audits, unpinned dependencies, and the real cost of ignoring JavaScript security warnings.

cover

Aug 20Article

Secure Communication Between Isolated React Native Instances

react-native-sandbox now supports secure, direct communication between sandboxed React Native instances, modeled after the web’s postMessage API with origin-based access control.

cover

May 13Article

React Native Legal: Zero-Config OSS License Screens for Your App

Add license acknowledgments to your React Native app with ease using React Native Legal-a zero-config tool for OSS compliance across iOS, Android, tvOS, and AndroidTV platforms.

cover

Jul 3Podcast

Authorization: Security Deep-Dive With Okta (Part 2)

Let's talk access control, delegated authorization, and more. Learn modern security frameworks and get tips for creating reliable apps.

cover

Jul 2Podcast

Authentication: Security Deep-Dive With Okta (Part 1)

Join us as we discuss authentication's past, present, and future. From MFA to passkeys, learn how to enhance security and efficiency in your applications.

cover

Feb 21Article

SSL Pinning in React Native Apps

Learn to implement SSL pinning to future-proof your React Native app against security attacks. Dig deeper into native SSL implementations for iOS & Android.

cover

Oct 28Article

Stripe Identity: ID Authentication Made Simple

Learn about preventing fraud with Stripe Identity React Native SDK.

cover

Nov 21Article

Secure Your React Native app

Learn how to make your React Native app as secure fot your application and customers.

cover

Mar 19Tutorial

The Hard Way vs. The React Native AI SDK Way: Stop Writing Custom Modules for Every Model

Learn how React Native AI uses a unified provider model to switch between cloud and on-device LLMs without rewriting application logic, enabling reliable AI experiences online and offline.

cover

Mar 12Tutorial

Build Smarter Apps: Tool Calling & AI Orchestration Explained

Learn how on-device models in React Native can call tools, interact with external APIs, and return structured outputs you can use directly in application logic.

cover

Mar 5Tutorial

MLC LLM + React Native: On-Device AI Without the Pain

Learn how to run third-party on-device LLMs in React Native using MLC LLM. Choose your models, run them efficiently across platforms, and keep a unified JavaScript API with React Native AI.

cover

Feb 24Tutorial

Intelligent Fallbacks with Apple Intelligence in React Native

Learn how to use Apple’s built-in Foundation Models in React Native apps, reduce memory usage, and enable fast, fully on-device AI with React Native AI Apple.

cover

Feb 10Tutorial

What Is the React Native AI SDK? A Complete Intro & Quickstart

Learn why on-device AI matters for React Native apps, how local LLMs behave offline, and what problems React Native AI is designed to solve from day one.

cover

Jan 29Tutorial

Implementing an Android TurboModule with Kotlin

Learn how to implement a React Native TurboModule on Android, from the TypeScript spec and Codegen to the Kotlin implementation and package registration.

cover

Jan 19Tutorial

Working with Different Threads in Swift TurboModules

Learn how JavaScript, native module, background, and main threads interact in React Native TurboModules, and how to use GCD queues to run async work safely in Swift.

cover

Jan 9Tutorial

How to Add Type-Safe Constants to Swift TurboModules

Learn how to expose typed, immutable constants from a Swift TurboModule using Codegen, and get full end-to-end type safety between native and JavaScript.

cover

Dec 30Tutorial

Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

cover

Dec 22Tutorial

Writing Your First TurboModule in Swift

Learn how to build a fully working TurboModule in Swift, integrate it with Codegen, and bridge it through Objective‑C inside an Expo app.