Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-14740] Android: Automatically generate ProGuard configuration file

GitHub Issuen/a
TypeNew Feature
PriorityHigh
StatusOpen
ResolutionUnresolved
Affected Version/sRelease 3.1.0
Fix Version/sn/a
ComponentsAndroid, CLI
Labelsexalture, notable
ReporterSoumya Kanti Kar
AssigneeJoshua Quick
Created2013-07-31T10:49:01.000+0000
Updated2019-11-07T00:40:12.000+0000

Description

Hi, Create a sample Android module and build it. Then follow this step by step. 1. Extract the contents of the zip file inside the dist folder. 2. Extract the JAR file obtained from the zip file. 3. Use JAD (Decompile tool) to decompile the any *.class file. You will observe that the entire source code is displayed. There is no obfuscation. I think Appcelerator must provide an obfuscation procedure during the build process. If any such process is present (using ProGuard for example), then can you please let us know. If no such process exists then it will be a great idea to add this feature. This will increase the security and also reduce the module size.

Attachments

FileDateSize
com.proguard.android.zip2014-10-23T22:45:22.000+00001273
proguard_app.zip2014-10-23T22:44:44.000+0000641685

Comments

  1. Soumya Kanti Kar 2013-08-02

    ProGuard can be used on the JAR that is created after building the Android module. We need to extract the JAR from the modile ZIP. Use ProGuard on the JAR keeping the classes that extend KrollModule and TiViewProxy. Repack the ZIP file. Then use the modified ZIP file in Appcelerator projects.
  2. Chris Barber 2014-01-16

    What's the immediate danger in allowing the .class files to be decompiled. They can just go to https://github.com/appcelerator/titanium_mobile and see the source with comments!
  3. Ingo Muschenetz 2014-04-14

    Note that you can use obfuscation now. This is a ticket to automatically generate the ProGuard file.
  4. Ingo Muschenetz 2014-04-28

    Note, here is a sample ProGuard file for Titanium. This may need to be updated to fit your usage (especially the file paths)!
       

    keep titanium class / package names

    -keepnames class org.appcelerator.** -keepnames class com.appcelerator.** -keepnames class ti.** -keepnames class android.widget.* -keepnames class kankan.wheel.widget.*- -keepnames class org.mozilla.javascript.**

    TODO: generate app ID here -keepnames com.company.id.**

    -keepnames class com.arcaner.proguard.test1.** -keeppackagenames

    preverification does nothing for dex

    -dontpreverify

    allows further optimization of getter/setter -> directly to field

    -allowaccessmodification

    dalvik specific optimization flags

    -optimizations !code/simplification/arithmetic

    app classes

    -injars /Users/username/Code/test/titanium/proguardTest1/build/android/bin/classes

    module jars

    -injars /Users/username/Code/titanium_mobile/dist/android/titanium-accelerometer.jar(!**/accelerometer.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-analytics.jar(!**/analytics.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-android.jar(!**/android.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-api.jar(!**/api.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-app.jar(!**/app.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-bump.jar(!**/bump.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-calendar.jar(!**/calendar.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-contacts.jar(!**/contacts.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-database.jar(!**/database.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-facebook.jar(!**/facebook.json,!META-INF/MANIFEST.MF,!**/LICENSE) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-filesystem.jar(!**/filesystem.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-geolocation.jar(!**/geolocation.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-gesture.jar(!**/gesture.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-json.jar(!**/json.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-locale.jar(!**/locale.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-map.jar(!**/map.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-media.jar(!**/media.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-network.jar(!**/network.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-platform.jar(!**/platform.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-ui.jar(!**/ui.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-utils.jar(!**/utils.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-xml.jar(!**/xml.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium-yahoo.jar(!**/yahoo.json,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/support/android/lib/titanium-verify.jar(!**/.gitignore,!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/dist/android/titanium.jar(!**/titanium.json,!META-INF/MANIFEST.MF,!**/*-NOTICE.txt,!**/.gitignore)

    bundled libs

    -injars /Users/username/Code/titanium_mobile/android/titanium/lib/ti-commons-codec-1.3.jar(!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/android/titanium/lib/commons-logging-1.1.1.jar(!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/android/titanium/lib/smalljs.jar(!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/android/modules/xml/lib/jaxen-1.1.1.jar(!META-INF/MANIFEST.MF) -injars /Users/username/Code/titanium_mobile/android/modules/bump/lib/bump-api.jar(!META-INF/MANIFEST.MF)

    library jars

    #-libraryjars /Users/username/Code/titanium_mobile/android/kroll-apt/lib/freemarker.jar -libraryjars /Users/username/Apps/android-sdk-mac_86/platforms/android-4/android.jar -libraryjars /Users/username/Apps/android-sdk-mac_86/add-ons/google_apis-4_r02/libs/maps.jar

    misc options

    commons codec/logging use a lot of reflection don't warn

    -dontwarn org.apache.commons.codec.binary.Base64 -dontwarn org.apache.commons.codec.binary.Hex -dontwarn org.apache.commons.logging.impl.ServletContextCleaner -dontwarn org.apache.commons.logging.impl.LogKitLogger -dontwarn org.apache.commons.logging.impl.AvalonLogger -dontnote org.apache.commons.logging.Log -dontnote org.apache.commons.logging.LogSource -dontnote org.apache.commons.logging.impl.Log4JLogger -dontnote org.apache.james.mime4j.message.storage.TempStorage

    bytecode compiled JS uses reflection to bootstrap

    -dontnote org.appcelerator.titanium.TiScriptRunner

    we use reflection for contacts api support post android r4

    -dontnote ti.modules.titanium.contacts.CommonContactsApi -dontnote ti.modules.titanium.contacts.ContactsApiLevel5

    reflection used to get the internal "applicationScale" member in TiPlatformHelper

    -dontnote org.appcelerator.titanium.util.TiPlatformHelper

    thirdparty classes

    -keep class org.mozilla.javascript.jdk13.VMBridge_jdk13

    app classes

    -keep class com.arcaner.proguard.test1.*

    module classes / methods

    -keep class ti.modules.titanium.TitaniumModuleBindingGen -keep class ti.modules.titanium.ui.UIModule -keep class ti.modules.titanium.ui.UIModuleBindingGen -keep class ti.modules.titanium.filesystem.FilesystemModule -keep class ti.modules.titanium.filesystem.FilesystemModuleBindingGen -keep class ti.modules.titanium.json.JSONModule -keep class ti.modules.titanium.json.JSONModuleBindingGen -keep class ti.modules.titanium.locale.LocaleModuleBindingGen -keep class ti.modules.titanium.android.AndroidModuleBindingGen -keep class ti.modules.titanium.app.AppModuleBindingGen -keep class ti.modules.titanium.api.APIModuleBindingGen -keep class ti.modules.titanium.media.MediaModuleBindingGen -keep class ti.modules.titanium.analytics.AnalyticsModuleBindingGen

    proxy binding classes

    -keep class org.appcelerator.titanium.**BindingGen -keep class ti.modules.titanium.ui.WindowProxyBindingGen -keep class ti.modules.titanium.ui.ButtonProxyBindingGen -keep class ti.modules.titanium.ui.LabelProxyBindingGen -keep class ti.modules.titanium.filesystem.FileProxyBindingGen
  5. Ingo Muschenetz 2014-04-28

    To use the ProGuard file: 1. Put a file called "proguard.cfg" in the project/platform/android directory 2. Create a CLI hook that ties into the pre-compile hook and sets builder.proguard to true.
  6. Ingo Muschenetz 2014-08-14

    Note, to configure for Crittercism: http://docs.crittercism.com/android/android.html#configuring-proguard-symbolication
  7. Ingo Muschenetz 2014-09-09

    It would b worth figuring out what a proper manually-generated ProGuard file looks like these days, and the algorithm for creating one.
  8. Alan Leard 2014-10-23

    I have attached a sample app that has Proguard enabled with the 3.4 SDK. It has a hacked together proguard.cfg file that probably needs some fixing, but the app and the plugin work. I will attach separately the Proguard plugin that is used in the app.
  9. Alan Leard 2014-10-23

    Here is the plugin required to manually enabled proguard. To enable, follow these steps: 1. Create plugins folder if one does not already exist 2. Add the attached plugin com.proguard.android to the plugins directory 3. Enable the plugin in tiapp.xml by adding
       <plugins>
            <plugin>com.proguard.android</plugin>
       </plugins>
       
    4. Add the ‘proguard.cfg' file in platform/android/ directory
  10. Stephen Feather 2014-10-29

    Alan, thank you. I'll try to get it put into an app tomorrow for testing.
  11. Travis Crist 2014-11-25

  12. Stephen Feather 2014-11-25

    I had to modify it all a bit. used -outjar to generated an intermediate jar that was reduced, then modify my proguard config to use it and not the regular jars and my apk was smaller. Ended up being faster at times, using google-play-services.jar for example, to use JarJar links to just clean that jar of unused methods before building and just skipping proguard. With libraries such as AWS, the proguard.cfg takes so long to setup and begin to declaring the used methods that its just a lot of wasted time. (no, the AWS recommended proguard.cfg does not work correctly out of the repo)
  13. Mark Mokryn 2014-12-05

  14. Ingo Muschenetz 2015-09-15

    [~hpham] [~cbarber] thoughts?
  15. Thomas Colliers 2015-11-06

    I've been trying to get this working. As mentioned before, the plugin and sample attached here do run ProGuard but do nothing with the output. Like Stephen I used -outjars to specify an output directory but I'm not sure how to make dexer pick up the processed folder instead of the original classes folder.
  16. Thomas Colliers 2015-11-06

    After many trial and error I finally got it working. I added 2 more event listeners to the plugin that move the classes folder to a temporary folder, proguard will then write to the classes directory so dexer can pick up the right files. I would attach the updated plugin and the proguard configuration I'm using but it seems I am unable to.
  17. Eduardo Gomez 2015-12-21

    [~thomascolliers] can you elaborate what did you have add to the event listeners? Probably post a dropbox link of plugin?
  18. Thomas Colliers 2015-12-30

    Here's the plugin code I'm using to switch out the Proguard output with the unobfuscated output so dexer can pick it up: (Linux/OSX only) https://paste.ee/p/8Y7tG
  19. Gary Mathews 2017-10-11

    Like [~jquick] and [~cbarber] mentioned, running ProGuard on a Titanium project will offer little to no benefit. The ProGuard config file provided seems to whitelist all of our Titanium namespaces which means they won't be optimised and obfuscated. Nor can they be, due to Titaniums use of reflection. The only benefit to running ProGuard would be in optimising the use of third-party libraries, reducing final APK size. ProGuard is marketed as a "source optimizer" and not a security measure (for that they suggest DexGuard). So if optimising is the priority, maybe [ReDex](https://github.com/facebook/redex) would be worth looking into? Since it will work regardless of our reflection requirements.
  20. Ben Bahrenburg 2017-10-11

    [~gmathews] I understand that the proxies cannot be obfuscated but shouldn't any internal classes be able to be obfuscated? This allows for any more sensitive operation to be moved into a plain old Java class. Without some form of obfuscation this will be a high / medium finding on any enterprise security review.
  21. Joshua Quick 2017-10-11

    [~ben.bahrenburg@gmail.com], Titanium and its modules are open source. So, obfuscating the code doesn't make a lot of sense (you can freely see the code on github). Just like how Google doesn't bother obfuscating their own open source Android libraries such as their support libraries. Plus, there is no 100% full-proof/future-proof automated way of obfuscating the code without issues since 3rd party code is out of our control and obfuscation would break their usage of reflection too... or features which use reflection indirectly such as via Java Serialization, GSON, HyperLoop, or possibly other means. If you're worried about code being tampered with (ie: your APK decompiled, code changed, re-compiled, and re-signed), then I think a better solution would be "tamper detection". This is what code signing is for. So, I think what you're really after here is the ability to check on startup that your APK is signed with the signature you originally signed it with. What do you think?
  22. Ben Bahrenburg 2017-10-12

    [~jquick] I 100% agree with your statement for commercial apps. The trouble happens when you enter the enterprise space. The approach you mention, ie don't obfuscate, doesn't match the OWASP guidelines, which govern most of the industry https://www.owasp.org/index.php/OWASP_Mobile_Security_Testing_Guide If this was native, the developer would need to determine the best proguard settings to cover both the app and their dependencies. I would recommend that we allow for the same opportunity for Ti. This does a few things. First allows your enterprise customers the flexibility in a "safe space" to be able show they are meeting the OWASP requirement. Secondly it allows the non proxy objects in the Ti framework or modules to be obfuscate. This allows for the ecosystem to more easily create the "tamper detection" methods you mentioned. Please note I've implemented the OWASP tamper detection methods within Titanium. I'm happy to discuss how these could be contributed back to the community.
  23. Joshua Quick 2017-10-12

    [~ben.bahrenburg@gmail.com], probably the simplest solution would be to set up ProGuard to not obfuscate anything using a Java @Kroll annotation. That would likely cover most of the reflection issues between JavaScript and Java in Titanium. That and any classes referenced in the AndroidManifest.xml would have to be on the list too. But from there, I think it would have to be the app developer's responsibility to disable obfuscation for any other APIs reflected upon via 3rd party code or by the app developer via HyperLoop. That's where I think we can't provide a 100% full-proof solution. But that said, it's not any better for a native developer using Android Studio either. Hmm...
  24. Ben Bahrenburg 2017-10-12

    Thanks [~jquick] . I think this would give the Ti developers the same footing, if not better (given JS encryption) than native developers. Is there anything that I can help with implementing or testing? Additionally happy to contribute the tamper methods if that would be helpful to core or AppC.
  25. Eric Merriman 2017-10-31

    Hello all, due to the volume of items and the schedule for 7.0.0 and the technological challenge for this feature, this ticket will be moved to 7.1.0.
  26. Muhammad Ahmed Fahad 2017-12-08

    Would really love to see this soon. Without this apps with multiple dex files are getting created which is totally incompatible with Android 4.X.X
  27. Joshua Quick 2018-01-24

    [~fahad86], in the upcoming Titanium 7.0.2 release, multidex'ed apps will be able to run on Android 4.x (see [TIMOB-25597]). ProGuard is not required. It'll just work.
  28. Muhammad Ahmed Fahad 2018-01-24

    @Joshua Quick :D happy for this. Thank you very much.

JSON Source