-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS code protection #1093
Comments
You could do this by using an encryption library to encode the JS and decode it at runtime before passing it to the bridge. The problem is that you'd have to ship the decryption key with the app code, so it would be trivial for a hacker to decrypt it if they were inclined to do so. I'd advise against including secret information in your application, even in native code. Code on the client is not secret - secrets should be kept on the server. |
So what's the answer here? (omitting your personal beliefs and opinions) Does the React project has any plans of protecting the developer's code or not? |
@nicklockwood Thanks for the reply. A determined hacker would get access to everything indeed, I'm talking more about "curious" people that might look into your house if you leave the door open ;) Also the are plenty of cases where you would really need to store some stuff on the device starting with complete offline apps to apps that communicate with external servers which you don't control. |
We're unlikely going to provide encryption or more sophisticated obfuscation. Right now, all the module names leak and we're thinking of replacing them with numbers for efficiency reason, which should help a bit if we end up doing it. |
But even with a more efficient code in place, the JS will still be in clear. Or am I getting it wrong? |
That's correct, it probably won't fit your usecase. We (as in Facebook) are not going to implement what you want anytime soon. That said, if you make the necessary changes inside of the codebase to have a pluggable way to inject an encryption/obfuscation plugin, that's something we may consider pulling in |
@vjeux clear now, thank you 😄 |
As @vjeux said, we have no immediate plans to add encryption for JS bundle files, and yes, under the currently recommended bundling instructions, your JS will be included as plaintext that can be extracted and de-obfuscated with relative ease. If you are just interested in preventing casual inspection of the JS source (as opposed to stopping a determined attacker) then I believe there is another way to bundle your code that will be much harder to crack (I've not tested this, so you'll have to try it and let me know if there are any problems):
Where AAAAAAAAAAAAA is your base64-encoded bundle. Then pass that URL into RCTRootView as normal to load your app. The advantage of embedding the source code in this way is that by including it as a string constant in your app (as opposed to a text file in the app resources) it will automatically be encrypted using Apple's FairPlay DRM when you upload it to the App Store. That means that anyone who downloads the app from the store and looks in the resources won't find the code, but more importantly even if they open the app binary in a hex editor they won't be able to find this base64 string and decode it because it will have been converted into encrypted gibberish. That makes it about as secure as ordinary native app code. A determined attacker could still open the app on a jailbroken device and use some tools to copy the decrypted binary out of RAM, but as I said earlier, there's really no practical defence against that. This approach will certainly push the difficulty out of the realm of "casual curiosity" though. Let me know if this works for you (or doesn't). It should be relatively easy to modify the packager to automate this if there's significant interest in doing it. |
@nicklockwood this should be good enough for a start, I'll run some tests and let you know. Thanks a bunch! |
You may want to test that the string in the binary is truly encrypted. I can't point to any mach-file docs (mobile atm), but in my experience large clobs are concatendated to the binary and are completely unencrypted. To test this download the App Store version of your app and run |
For the record, thousands of Cordova apps are shipped to the app stores with all resources unencrypted. Just saying... JG :: sent from my mobile device ::
|
@shayne thank you. I'll keep this in mind. @jaygarcia For many apps this might be a "nice to have" however for most of my projects the code protection is required :) |
Chiming in here as I've done quite a bit of work around license key protection and sorts. Please realise no matter how much effort you put in to "securing" your JS code or secrets in an iOS client app a determined attacker will always get what they want. From what I've read from other developers it's about a 10:1 effort. That is for every 10 hours you spend "protecting" your stuff it takes an attacker approx 1 hour to reverse your efforts. Trying to keep the source private is pretty moot-point since it's very easy to monitor some of the Objective-C code that react-native uses. The best thing I recommend to anyone is to ensure your jsbundle has a signature and you verify that signature before you let it be loaded into the bridge. This is especially important for anyone delivering updates over HTTP/HTTPS. If you are heavily worried about code protection use heavy obfuscation and RSA public/private keys to encrypt the source. Again anyone with a jailbroken device and a bit of time can easily latch LLDB onto the RCTBridge methods and snag your code. |
Thanks Robert!! JG :: sent from my mobile device ::
|
@rborn did you get a chance to try my suggestion? Any problems? |
Sorry, I'm traveling this days and I'll be able to touch the code only the next week. Sent from my iPhone
|
I'm really sorry for the delay. @nicklockwood I did what you suggested (base64 the jsbundle) and the test app works ok (deployed both on sim and device). However after I generated the ipa for appstore a |
Ah, pity. The next option would be to encrypt the base64 URL and then decrypt it before passing to the bridge then. Not very much harder, but still an extra step. Doesn't really matter if the string is stored in the app or in a file. |
Wait, when you say generated ipa for app store, do you mean you submitted it to Apple and then downloaded in iTunes once it was approved and released, or did you just export a release build from xcode? The encryption is applied by Apple in the cloud, so it doesn't encrypt the ipa before you actually submit it. |
Oh, didn't know this, I thought the encryption is done locally. |
Fairplay encryption is only applied to certain parts of the app binary itself, not to assets in the resources folder (they unzip your ipa, add the encryption, and then reassemble the ipa) |
I see, thank you Sadly I cannot test right now with an app in appstore 😞 |
Very interesting discussion, good to see some options presented here. Given that this is outside of the scope of React Native itself, let's move the discussion to discuss.react.js.org if there's anything left to be said! @rborn - feel free to ping us again in this discussion with followup if you do get a chance to test it in the app store! |
Is there a recommended tool to use for obfuscation of react native javascript code? Can I use something like Uglify? |
I tried the Base64 encoding of jsbundle file in iOS, and it works great. |
@sudarshanJagtap Hi, maybe I know how to do the Base64 encoding of jsbundle file in iOS ? |
Can their be some directions to the community as to how to implement obfuscation or alternative security measures in the js bundle? |
The JavaScript is already obfuscated with the minifier. The security (not sure if that's the right word...) is comparable to a website's. RN's packager already ships with that. |
+1 to automate the jsCodeLocation trick. Is there anything similar for Android? |
@rborn @brentvatne |
@sudarshanJagtap @jesucarr Hey guys! How you did base64 "in details"? |
I have implemented embedding of jsbundle in #12587 |
For someone trying to figure it out. Here are the steps:
|
I'm having problems with static resources. After using this process, all my images are gone from release app. If I understand it correctly, RN looks for the "assets" directory in the same folder as "main.jsbundle". But now I don't have main.jsbundle file. |
Yeah same problem here. Also the the loading of the js code is very slow now. Used to take 3 seconds, now its over 10s. |
@chatras Are you testing this in a prod build? |
How should we use |
In Android it doesn't make any sense as strings are not encrypted upon binary download. Additionally there were problems with loading resources and performance with base64 approach. |
Hi @chatras , @nicklockwood , I am trying to use this code but its not working. I don't think. its decode the JSBUNDLE_BASE64. can you please explain meaning of this line. |
@nitinsoni9235 first thing first, don't do it. It's a false sense of security. More details here #12587 |
Hi everyone,
Is there any plan to encrypt the javascript code in production mode (release for AppStore)?
I know that right now it can be obfuscated, but this it's not enough :)
Thank you.
The text was updated successfully, but these errors were encountered: