When you build an Android app, you are responsible for its security. When you build an Android SDK or library, you are responsible for the security of every app that uses it. A single vulnerability in your SDK can have a massive blast radius, affecting thousands of apps and millions of users.
Building a secure SDK requires a different mindset. You are a guest in another developer's application, and you must be a well-behaved one. This checklist covers the essential security practices every SDK developer should follow to build trust and protect the entire ecosystem.
1. Practice Permission Minimalism
This is the golden rule. Only declare permissions that are absolutely essential for your SDK's core functionality. Do not add permissions for features that are optional or might be useful in the future. Every permission you add increases the host app's attack surface and requires the user to grant a trust that might not be necessary.
If a feature requires a sensitive permission (like `ACCESS_FINE_LOCATION`), make its inclusion optional. Allow the host app developer to decide if they want to add that permission themselves to enable the feature.
2. Harden Your Code with R8/ProGuard
Your SDK's intellectual property and internal logic are valuable. You must make it as difficult as possible for attackers to reverse-engineer. Be aggressive with your ProGuard/R8 configuration.
- Obfuscate Everything: Rename all non-public classes, methods, and fields.
- Remove Logging: Strip out all logging statements from your release builds.
- Define a Public API: Use
-keep
rules only for the public classes and methods that developers are meant to interact with. Everything else should be obfuscated.
# Keep only the public entry points to the SDK
-keep public class com.androshelf.sdk.AndroShelfSDK {
public static void init(...);
public ...;
}
# Keep public models that are part of the API
-keep public class com.androshelf.sdk.models.** { *; }
# Aggressively obfuscate all internal implementation details
-repackageclasses 'com.androshelf.sdk.internal'
-allowaccessmodification
3. Handle Data with Extreme Care
Your SDK should be a black box when it comes to data. It should not store sensitive information unless absolutely necessary, and if it does, it must be encrypted.
- Avoid Persistent Storage: Do not write data to SharedPreferences or a database unless it's critical. If you do, use Jetpack Security to encrypt it.
- Be Transparent: Clearly document what data your SDK collects, how it's used, and your data retention policies. This is essential for the host app's privacy policy.
- Use App-Specific Storage: Never write files to shared external storage. Always use the app's sandboxed internal storage.
4. Design a Secure Public API
Design your SDK's public API to be "pit-of-success" oriented, meaning it should be hard for developers to misuse it in an insecure way.
- Validate All Inputs: Never trust the data passed into your SDK from the host app. Sanitize and validate all parameters.
- Avoid Insecure Patterns: For example, don't create a method that takes a raw SQL string to execute. This opens the door to SQL injection if the app developer isn't careful.
- Provide Secure Defaults: If your SDK has configurable settings, the default options should always be the most secure ones.
5. Manage Your Dependencies
Your SDK's vulnerabilities are not just in your own code, but also in the third-party libraries you depend on. A vulnerable version of OkHttp or Gson in your SDK makes every app that uses your SDK vulnerable too.
- Minimize Dependencies: Only include libraries you absolutely need.
- Use Dependency Analysis Tools: Regularly run tools like the OWASP Dependency-Check plugin or Snyk to scan your dependencies for known vulnerabilities (CVEs).
- Shade Dependencies (If Necessary): To avoid version conflicts with the host app, consider "shading" (repackaging) your dependencies using a tool like the Gradle Shadow Plugin.