Android App Security Checklist
Phase 0: Governance, environment, and CI/CD
Enforce CI gates
- Run static checks on every PR: ktlint / Android Lint, unit/UI tests, dependency audit (Gradle, SBOM).
- Block release on High/Critical SAST/SCA/DAST findings; zero lint errors on release branches.
Secrets handling
- No secrets in source, BuildConfig, AndroidManifest.xml, resources, or logs.
- Use environment/secret manager (e.g., Gradle secrets, cloud KMS); redact secrets in analytics.
- Rotate keys/tokens periodically and on suspicion of leakage.
Evidence and traceability
- Archive scan reports, SBOM, build logs, and release notes with each artifact.
Scanning automation
- Integrate a mobile SAST/DAST/SCA platform in CI/CD to run on each PR and pre‑release and automatically fail gates on High/Critical issues.
Phase 1: Threat modeling, data classification, and inventory
- Classify data (PII, credentials, tokens, payment) and map collection, processing, storage (SharedPreferences, files, databases, Keystore), and transmission.
- Identify trust boundaries (device, app sandbox, Keystore, IPC/Binder, WebView, native libraries, backend APIs).
- Inventory third‑party SDKs; prefer well‑maintained, signed, least‑privilege SDKs; minimize count.
Phase 2: Build and configuration hardening (Gradle + Manifest)
Gradle/Release settings
- Use release builds with code shrinking/obfuscation (
minifyEnabled true,shrinkResources true). - Strip debug symbols from shipped APK/AAB.
- Keep mapping files server‑side.
- Exclude test/debug libraries from release.
- Remove development endpoints and feature flags from production builds.
Signing and permissions
- Protect signing keys (hardware‑backed keystores, restricted access).
- Use dedicated release signing configs.
- Declare only necessary permissions in
AndroidManifest.xml. - Avoid excessive dangerous permissions.
Network security config
- Use
networkSecurityConfigto enforce TLS. - Disallow cleartext traffic (
android:usesCleartextTraffic="false"). - Use domain config overrides only when necessary and time‑boxed.
Manifest hygiene
- Do not set components
exported="true"unless strictly required; restrict with permissions when exported. - Remove debug flags (
android:debuggable="false"in release, noallowBackup="true"unless needed with proper encryption). - Provide accurate permission rationale text (in‑app) for all runtime permissions.
Phase 3: Local storage and Keystore security
Keystore usage
- Store long‑lived keys in Android Keystore with strongest feasible protection (hardware‑backed when available, user auth if UX permits).
- Use
setUserAuthenticationRequired(true)for highly sensitive keys; gate operations with biometrics/lockscreen where appropriate. - Delete Keystore‑wrapped secrets on logout or device change.
- Consider device‑binding for high‑risk tokens.
Files, SharedPreferences, and databases
- Avoid storing secrets or sensitive PII in plaintext files or
SharedPreferences. - Encrypt sensitive databases/files (e.g., SQLCipher or equivalent file encryption).
- Use app‑private storage (
MODE_PRIVATE). - Apply file protection flags where supported.
- Ensure backups do not contain unencrypted secrets.
Caches and derived data
- Avoid persisting PII in caches/temp.
- Purge caches/temp on logout and as part of backgrounding if appropriate.
- Do not write secrets to logs or
SharedPreferenceseven temporarily.
Phase 4: Privacy safeguards (UI, clipboard, screenshots)
- Redact sensitive UI in app switcher screenshots (e.g., use
FLAG_SECUREon sensitive Activities/Views). - For highly sensitive flows, consider additional masking or separate “secure mode” Activities.
- Avoid reading clipboard on app launch; never place passwords/long‑lived tokens on the clipboard.
Phase 5: Network security and TLS/pinning
HTTPS/TLS enforcement
- Enforce HTTPS to trusted hosts; reject invalid certificates/hostnames; disable HTTP fallbacks.
- Configure strict timeouts, exponential backoff with jitter, and fail closed on TLS errors.
Certificate pinning
- Prefer SPKI SHA‑256 pins; include at least one backup pin per host.
- Implement pinning via OkHttp / custom
TrustManagerornetworkSecurityConfig. - Validate against MITM and expired/rotated leaf scenarios.
- Plan safe pin rotation; include telemetry on pin failures.
Cookies and tokens
- For web flows, use secure, HttpOnly, SameSite cookies.
- Avoid long‑lived bearer tokens on device.
- Clear cookies and WebView data after sensitive sessions.
Phase 6: Authentication, authorization, and session
Auth flows
- Use OAuth2/OIDC with PKCE for public clients; never embed client secrets in the app.
- Prefer system/browser‑based auth (Chrome Custom Tabs / default browser) over in‑app WebView for login.
Tokens
- Use short‑lived access tokens.
- Store refresh tokens only in encrypted storage bound to Keystore keys.
- Rotate and invalidate tokens on logout, device change, and suspicious activities.
- Bind sessions to device risk where appropriate.
Authorization
- Enforce authorization server‑side; treat client checks as advisory only.
- Test and prevent IDOR/BOLA and privilege escalation across all backend APIs used by the app.
Phase 7: WebView hardening
- Use WebView only when required; prefer browser for authentication and payment when possible.
Defaults
- Disable JavaScript unless strictly necessary.
- If JavaScript is enabled, restrict capabilities and disable
setAllowFileAccessFromFileURLsandsetAllowUniversalAccessFromFileURLs. - Do not enable
addJavascriptInterfacewith objects that expose sensitive methods, especially on API < 17. - Enforce navigation allowlists (hosts/paths); block
file://,javascript:, and untrusted schemes. - Use non‑persistent WebView storage for sensitive sessions where feasible.
- Clear cookies, cache, and history on logout.
Content security
- Serve first‑party web content over HTTPS only.
- Disallow mixed content (
MIXED_CONTENT_NEVER_ALLOW). - Ensure remote content is integrity‑checked and controlled (no untrusted third‑party scripts unless strictly necessary).
Phase 8: Inter‑app communication and deep links
- Prefer App Links (verified links) for deep linking; validate incoming link origins and parameters.
Custom schemes and intents
- If custom schemes or implicit intents are used, ensure uniqueness and robust validation of all incoming data.
- Protect exported Activities/Services/BroadcastReceivers with permissions or explicit intents; avoid overly broad intent filters.
- Defend against intent spoofing, URL hijacking, and open redirects by checking caller identity and parameters.
Phase 9: Reverse engineering and tamper resilience
Reduce static leakage
- Remove debug builds, verbose logs, debug menus, and test endpoints from release builds.
- Obfuscate and shrink code (ProGuard/R8) and resources.
- Avoid leaving meaningful strings (API keys, secrets) in resources or native libraries.
Environment checks
- Detect root/hooking/debugger indicators (common root paths, writable system dirs, instrumentation frameworks) and log signals.
- Respond proportionally (reduced functionality, additional verification, or block) based on risk, while maintaining UX.
Tamper testing
- Ensure repackaged or re‑signed apps fail integrity checks or server attestation (e.g., safety/attestation APIs).
- Treat client‑side signals as hints to the backend; never as the sole security control.
Phase 10: Cryptography and randomness
- Use platform‑provided crypto primitives (Java Cryptography Architecture, Android Keystore); do not build custom algorithms.
- Use modern AEAD modes like AES‑GCM/ChaCha20‑Poly1305 for authenticated encryption.
- Use established KDFs (PBKDF2/HKDF) with proper parameters and salts.
- Generate keys/IVs with a secure RNG (
SecureRandomor platform APIs). - Never reuse IVs/nonces.
- Keep keys in Keystore or encrypted at rest.
Phase 11: Permissions, notifications, and identifiers
- Request minimum permissions, at point‑of‑use, with clear in‑context explanations of value to the user.
Privacy‑related permissions
- Limit access to location, contacts, camera, microphone, storage, and phone state to strict necessity.
- Handle denial and revocation gracefully.
- Avoid dark patterns that pressure users.
Identifiers and tracking
- Prefer app‑scoped or resettable identifiers; avoid building persistent fingerprinting across apps.
- Use advertising or analytics IDs only according to platform policies.
- Never use prohibited hardware identifiers for tracking.
Notifications
- Minimize sensitive data in notification content.
- Use generic wording and hide details on lock screen when possible.
Phase 12: Logging, analytics, and crash reporting
- Use structured logging with severity levels; disable verbose/debug logging in release builds.
- Redact PII and secrets from logs, analytics events, and crash reports.
- Aggregate and sample analytics where possible.
- Ensure symbol/mapping files for obfuscated builds are stored securely server‑side for crash de‑obfuscation.
- Do not ship symbol/mapping files inside the app.
Phase 13: Testing, DAST, and runtime verification
Traffic interception tests
- Verify resistance to MITM (invalid certs, hostname mismatch, untrusted CA).
- Verify that pinning blocks interception where configured.
Runtime inspection
- Confirm no secrets/PII appear in logs.
- Verify sensitive data is encrypted at rest.
- Review WebView behavior at runtime (navigation, JS, storage).
- Review local storage behavior at runtime (files, SharedPreferences, databases).
- Validate that Keystore‑backed keys are used where expected.
- Validate that access controls for Keystore keys behave as designed.
API abuse tests
- Test rate limiting.
- Test replay protection.
- Test pagination bounds.
- Test for mass assignment.
- Test error message hygiene for backend APIs.
Dynamic analysis
- Run mobile DAST while exercising core flows to surface transport misconfigurations, WebView issues, storage leaks, and logging problems.
- Export evidence from DAST for triage and re‑tests.
Phase 14: SBOM, and evidence
SBOM and dependencies
- Generate SBOM for all Gradle modules and embedded SDKs.
- Track CVEs and update dependencies regularly.
- Monitor dependency health as part of release readiness.
- Monitor license compliance as part of release readiness.
Evidence bundle
- Attach scan artifacts to the release record.
- Attach SBOM to the release record.
- Attach manifest diffs to the release record.
- Attach permission and component export lists to the release record.
- Attach automated/manual test reports to the release record.
Phase 15: Reporting and standards alignment
Report
- Provide executive summary, scope/methodology, detailed findings with PoCs/evidence, risk ratings, remediation guidance, and re‑test results.
Standards mapping (example)
- ARCH: Phases 1–2
- PLATFORM: Phases 2, 7–8, 11
- STORAGE: Phases 3–4
- CRYPTO: Phase 10
- AUTH: Phase 6
- NETWORK: Phase 5
- CODE: Phases 2, 9, 12
- RESILIENCE: Phase 9
Practitioner quick‑reference
- Manifest/Network: No cleartext traffic in release; strict
networkSecurityConfigdomains; avoid exporting components without strong justification. - Secrets & storage: Use Android Keystore for long‑lived keys; encrypt DB/files; never store secrets in
SharedPreferencesor logs. - Network: HTTPS only; certificate/SPKI pinning with backups for critical endpoints; verify MITM attempts fail.
- Auth: OIDC + PKCE; short‑lived access tokens; refresh tokens in encrypted storage; server‑side authorization; test IDOR/BOLA.
- WebView: Prefer browser for auth; if WebView, JS off by default, restrict interfaces, allowlist navigation, non‑persistent store for sensitive flows.
- Privacy: Use
FLAG_SECUREfor sensitive screens; avoid clipboard secrets; minimize permissions and provide clear explanations. - Release hygiene: Obfuscate and shrink; remove debug logs/menus/test endpoints; validate permissions and exported components each release.