MyFamilyTracker
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Security vulnerabilities in Android apps can expose user data, bypass authentication, and get your app removed from the Play Store. Here's a practical security testing checklist developers can run themselves.
On this page
You don't need a dedicated security team to catch the most common Android vulnerabilities. Most security issues follow predictable patterns that you can find with the right checklist.
Here's what to check before every release.
The most common category of Android vulnerabilities: storing sensitive data where it shouldn't be.
SharedPreferences
SharedPreferences are stored in plain text on the device. Never store passwords, tokens, or PII here.
// BAD — user token in SharedPreferences
prefs.edit().putString("auth_token", userToken).apply()
// GOOD — use EncryptedSharedPreferences
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val encryptedPrefs = EncryptedSharedPreferences.create(
context,
"secure_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)Internal vs External Storage
Files in external storage (Downloads, SDCard) are accessible to other apps with READ_EXTERNAL_STORAGE permission. Sensitive files belong in internal storage:
// Internal storage — app private
val file = File(context.filesDir, "user_data.json")Logging
Logs in release builds are a data leak. Search your codebase for:
grep -r "Log\.d\|Log\.v\|Log\.i\|println" --include="*.kt" app/src/main/Any log statement that includes tokens, passwords, PII, or API keys is a vulnerability. Use ProGuard to strip logs in release:
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** d(...);
public static *** i(...);
}Certificate Pinning
SSL/TLS prevents eavesdropping, but a MITM attack with a trusted CA can still intercept traffic. Certificate pinning ensures your app only accepts your server's specific certificate.
val certificatePinner = CertificatePinner.Builder()
.add("api.yourapp.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()Network Security Config
Prevent cleartext (HTTP) traffic in production:
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<debug-overrides>
<trust-anchors>
<certificates src="user" /> <!-- allows Charles/Fiddler in debug -->
</trust-anchors>
</debug-overrides>
</network-security-config><!-- AndroidManifest.xml -->
<application
android:networkSecurityConfig="@xml/network_security_config">Token Storage
Auth tokens don't belong in SharedPreferences (see above). Use the Android Keystore system or EncryptedSharedPreferences.
Token Expiry
Verify that:
Biometric Authentication
If using biometric auth, verify it's tied to a Keystore key — not just a boolean flag:
// WRONG — biometric just unlocks a boolean
if (biometricPassed) {
showSecureContent()
}
// RIGHT — biometric unlocks a key that decrypts the data
val cipher = getCipherForDecryption() // tied to Keystore key with biometric binding
biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher))Exported Components
Every Activity, Service, BroadcastReceiver, and ContentProvider with
android:exported="true"<!-- Only export components that need to be external -->
<activity android:name=".MainActivity" android:exported="true" />
<!-- Internal activities should NOT be exported -->
<activity android:name=".InternalSettingsActivity" android:exported="false" />Audit your manifest. Every exported component should have a justification.
Permissions
Review requested permissions:
Remove any permission your app doesn't actually use.
Mobile Security Framework (MobSF) performs automated static analysis on your APK:
# Run MobSF via Docker
docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
# Open http://localhost:8000
# Upload your APK
# Get a comprehensive security reportMobSF catches:
Run this before every major release.
# Check for hardcoded secrets in code
grep -r "password\|api_key\|secret\|token" --include="*.kt" app/src/main/ -i
# Check for http:// URLs (should be https://)
grep -r "http://" --include="*.kt" --include="*.xml" app/src/
# Check for overly broad file permissions
grep -r "MODE_WORLD_READABLE\|MODE_WORLD_WRITEABLE" --include="*.kt" app/src/Sudarshan Chaudhari
AI Systems Builder / Product Engineer
Bangkok, Thailand
Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.
Related Posts
Related Apps
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Building something? Available for Android dev and QA consulting.
Work with meComments — powered by Giscus
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
ReadPrivate dream journal — structured entry capture, pattern tagging, and optional Claude-powered insight generation. All data stays on-device by default.
ReadWorkout tracker — exercise logging with set/rep/weight history, goal progression, and local Room DB persistence. No account, no cloud sync required.
Read