deardaniel/secdata-raw huggingface dataset:
OWASP Mobile Application Security Testing Guide: MASTG BEST 0029

---
title: Implementing Resilience and RASP Signals
alias: implementing-resilience-and-rasp-signals
id: MASTG-BEST-0029
platform: generic
knowledge: [MASTG-KNOW-0027, MASTG-KNOW-0028, MASTG-KNOW-0029, MASTG-KNOW-0030, MASTG-KNOW-0031, MASTG-KNOW-0032, MASTG-KNOW-0033, MASTG-KNOW-0034, MASTG-KNOW-0035]
status: placeholder
note: Resilience controls and RASP (Runtime Application Self-Protection) style checks are defense in depth measures that raise attacker cost by detecting risky environments and runtime tampering. They do not replace secure design and they are inherently bypassable, so they should be selected and tuned based on the app's threat model and risk tolerance.
---
OWASP Mobile Application Security Testing Guide: MASTG BEST 0020

---
title: Update the GMS Security Provider
alias: update-gms-security-provider
id: MASTG-BEST-0020
platform: android
knowledge: [MASTG-KNOW-0011]
---

Android devices vary widely in OS version and update frequency. Relying solely on platform-level security can leave apps exposed to outdated SSL/TLS implementations and known vulnerabilities.

**The GMS Security Provider** (delivered via Google Play Services) addresses this by updating critical cryptographic components—such as `OpenSSL` and `TrustManager`, **independently of the Android OS**. This helps ensure **secure network communication**, even on older or unpatched devices.

It is strongly recommended to check and update the Security Provider **early during app startup**, ideally before making any secure network connections. Follow the Android Developer Documentation on [how to update the Security Provider to protect against SSL exploits](https://developer.android.com/privacy-and-security/security-gms-provider "Updating Your Security Provider to Protect Against SSL Exploits").

If your app needs to support devices both **with and without Google Play Services** (such as Huawei devices, Amazon tablets, or AOSP-based ROMs), implement runtime checks to detect Play Services availability.

- On GMS-enabled devices, use the Security Provider to keep cryptographic libraries up to date.
- On non-GMS devices, consider bundling a secure TLS library like [Conscrypt](https://conscrypt.org) to ensure consistent and strong network security across your entire device fleet.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0018

---
title: Use `SecureFlagPolicy.SecureOn` to Prevent Screenshots in Compose Components
alias: use-secureon-in-compose-components
id: MASTG-BEST-0018
platform: android
status: placeholder
note: Preventing screenshots and screen recording helps protect sensitive data from being exposed in system-generated snapshots and recordings.
---
OWASP Mobile Application Security Testing Guide: MASTG BEST 0027

---
title: Preventing Sensitive Data Exposure in Notifications
alias: preventing-sensitive-data-exposure-in-notifications
id: MASTG-BEST-0027
platform: android
knowledge: [MASTG-KNOW-0054]
status: placeholder
note: This best practice is about handling sensitive data in notifications on Android devices, such as avoiding exposure completely or setting appropriate visibility levels.
---
OWASP Mobile Application Security Testing Guide: MASTG BEST 0028

---
title: WebViews Cache Cleanup
alias: android-webviews-cache-cleanup
id: MASTG-BEST-0028
platform: android
---

Android WebViews cache data when the server responds with specific `Cache-Control` headers that instruct the browser to cache the content. If a WebView processes sensitive data, you should ensure that no residual information remains on the device (disk and/or RAM) once the WebView is no longer required.

Prefer server-side cache prevention by using headers such as `Cache-Control: no-cache` in API responses that contain sensitive data to instruct the webview not to cache.

If server-side control is not possible or as a supplementary control, explicitly set [`WebSettings.setCacheMode()`](https://developer.android.com/reference/android/webkit/WebSettings#setCacheMode(int)) with [`WebSettings.LOAD_NO_CACHE`](https://developer.android.com/reference/kotlin/android/webkit/WebSettings#LOAD_NO_CACHE:kotlin.Int) or clear the WebView cache with [`WebView.clearCache(includeDiskFiles = true)`](https://developer.android.com/reference/android/webkit/WebView#clearCache(boolean)) after WebView use (such as on WebView Activity's `onDestroy` lifecycle call) to reduce this risk. However, this method comes with two disadvantages:

1. The first disadvantage is indiscriminately deleting all cached data, including non-sensitive items that actually benefit from the cache, such as bigger files like images.
2. The second disadvantage is the lack of a guarantee that the clear method will always be called, particularly if the app process is killed abruptly. In this case, evaluation of prior cache clearing and active clearing would be required, such as at the next app start.

@MASTG-KNOW-0018 describes the different storage areas used by WebViews.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0031

---
title: Enforce Strong Biometrics for Sensitive Operations
alias: enforce-strong-biometrics-for-sensitive-operations
id: MASTG-BEST-0031
platform: android
knowledge: [MASTG-KNOW-0001]
---

For sensitive operations protected by Android biometrics, configure `BiometricPrompt` to require [`BIOMETRIC_STRONG`](https://developer.android.com/reference/androidx/biometric/BiometricManager.Authenticators) rather than allowing weaker biometric classes. Android defines `BIOMETRIC_STRONG` as authentication using a Class 3 biometric, while `BIOMETRIC_WEAK` corresponds to Class 2 biometric authentication.

When the operation is intended to be biometric only, don't include `DEVICE_CREDENTIAL` in the allowed authenticators. `DEVICE_CREDENTIAL` enables fallback to the device screen lock credential (PIN, pattern, or password) instead of requiring a biometric factor. While not inherently a vulnerability, for high-security applications (e.g., finance, government, health) its use reduces the intended security posture and makes authentication more susceptible to shoulder surfing and social engineering.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0021

---
title: Ensure Proper Error and Exception Handling
alias: ensure-proper-error-and-exception-handling
id: MASTG-BEST-0021
platform: android
knowledge: [MASTG-KNOW-0010]
---

Secure exception and error handling in Android is about preventing the leakage of sensitive information, managing failures gracefully, and ensuring that errors do not compromise security. User-facing error messages should remain generic, while controlled logging is reserved for developers. The [OWASP DevGuide](https://devguide.owasp.org/en/04-design/02-web-app-checklist/10-handle-errors-exceptions/) reinforces these principles with a focus on not disclosing internal details to end users, not disclosing sensitive user data to developers, and ensuring secure failure modes that do not weaken authentication or authorization.

- **Avoid leaking sensitive information**: Error messages shown to users should be generic and not reveal internal details. Logs should be sanitized to remove sensitive data and restricted to authorized personnel. The official [Log Info Disclosure](https://developer.android.com/privacy-and-security/risks/log-info-disclosure) guidance warns against including sensitive data or stack traces in production logs and recommends sanitization and reduced verbosity.
- **Fail securely**: Exceptions must not weaken security controls. Any failure in security checks should result in a **deny** outcome, blocking the action rather than allowing weaker assumptions or insecure fallbacks. Security mechanisms should default to denying access until explicitly granted, since fail-open paths are a common attack vector.
- **Validate strictly and abort on errors**: Unexpected formats or values should be treated as errors. Do not continue in a partially verified state. For example, if a network call succeeds at the transport layer but fails validation at the application layer, processing must stop. If the validation fails, do not try to sanitize the data to make the validation succeed.

See these resources for more details:

- ["OWASP - Fail Securely"](https://owasp.org/www-community/Fail_securely)
- ["OWASP - Improper Error Handling"](https://owasp.org/www-community/Improper_Error_Handling)
- ["CWE-636 - Not Failing Securely ('Failing Open')"](https://cwe.mitre.org/data/definitions/636.html)
OWASP Mobile Application Security Testing Guide: MASTG BEST 0037

---
title: Invalidate Biometric Keys on Enrollment Changes
alias: invalidate-biometric-keys-on-enrollment-changes
id: MASTG-BEST-0037
platform: android
knowledge: [MASTG-KNOW-0001]
---

When generating cryptographic keys for biometric authentication, ensure keys are invalidated when new biometrics are enrolled. Either configure [`setInvalidatedByBiometricEnrollment(true)`](https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder#setInvalidatedByBiometricEnrollment(boolean)) explicitly, or rely on the default behavior, which invalidates keys when `setUserAuthenticationRequired(true)` is set.

When `setInvalidatedByBiometricEnrollment(false)` is used, a key remains valid even after new biometrics are enrolled. An attacker who obtains the device passcode could enroll a new biometric and use it to access existing encrypted data or trigger sensitive operations.

By invalidating keys on enrollment changes, only biometrics that were enrolled when the key was created can unlock it, preventing newly enrolled biometrics from accessing previously protected data.

!!! note
    Key invalidation is immediate and permanent when a new biometric is enrolled. The app must handle [`KeyPermanentlyInvalidatedException`](https://developer.android.com/reference/android/security/keystore/KeyPermanentlyInvalidatedException) and guide the user to re-authenticate to create a new key.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0026

---
title: Preventing Keyboard Caching for Sensitive Text Inputs
alias: preventing-keyboard-caching-for-sensitive-text-inputs
id: MASTG-BEST-0026
platform: ios
knowledge: [MASTG-KNOW-0100]
status: placeholder
note: This topic explains best practices to prevent sensitive text inputs from being cached by the iOS keyboard.
---
OWASP Mobile Application Security Testing Guide: MASTG BEST 0002

---
title: Remove Logging Code
alias: remove-logging-code
id: MASTG-BEST-0002
platform: android
knowledge: [MASTG-KNOW-0049]
---

Ideally, a release build shouldn't use any logging functions, making it easier to assess sensitive data exposure.

## Using ProGuard

While preparing the production release, you can use tools like @MASTG-TOOL-0022 (included in Android Studio). To determine whether all logging functions from the `android.util.Log` class have been removed, check the ProGuard configuration file (proguard-rules.pro) for the following options (according to this [example of removing logging code](https://www.guardsquare.com/en/products/proguard/manual/examples#logging "ProGuard\'s example of removing logging code") and this article about [enabling ProGuard in an Android Studio project](https://developer.android.com/studio/build/shrink-code#enable "Android Developer - Enable shrinking, obfuscation, and optimization")):

```default
-assumenosideeffects class android.util.Log
{
  public static boolean isLoggable(java.lang.String, int);
  public static int v(...);
  public static int i(...);
  public static int w(...);
  public static int d(...);
  public static int e(...);
  public static int wtf(...);
}
```

Note that the example above only ensures that calls to the Log class' methods will be removed. If the string that will be logged is dynamically constructed, the code that constructs the string may remain in the bytecode. For example, the following code issues an implicit `StringBuilder` to construct the log statement:

Example in Java:

```java
Log.v("Private key tag", "Private key [byte format]: " + key);
```

Example in Kotlin:

```kotlin
Log.v("Private key tag", "Private key [byte format]: $key")
```

The compiled bytecode, however, is equivalent to the bytecode of the following log statement, which constructs the string explicitly:

Example in Java:

```java
Log.v("Private key tag", new StringBuilder("Private key [byte format]: ").append(key.toString()).toString());
```

Example in Kotlin:

```kotlin
Log.v("Private key tag", StringBuilder("Private key [byte format]: ").append(key).toString())
```

ProGuard guarantees removal of the `Log.v` method call. Whether the rest of the code (`new StringBuilder ...`) will be removed depends on the complexity of the code and the [ProGuard version](https://stackoverflow.com/questions/6009078/removing-unused-strings-during-proguard-optimisation "Removing unused strings during ProGuard optimization ").

This is a security risk because the (unused) string leaks plain text data into memory, which can be accessed via a debugger or memory dumping.

Unfortunately, no silver bullet exists for this issue, but one option would be to implement a custom logging facility that takes simple arguments and constructs the log statements internally.

```java
SecureLog.v("Private key [byte format]: ", key);
```

Then configure ProGuard to strip its calls.

## Custom Logging

You can implement a custom logging facility and disable it at once only for the release builds.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0007

---
title: Debuggable Flag Disabled in the AndroidManifest
alias: debuggable-flag-disabled
id: MASTG-BEST-0007
platform: android
knowledge: [MASTG-KNOW-0007]
---

Ensure the debuggable flag in the AndroidManifest.xml is set to `false` for all release builds.

**Note:** Disabling debugging via the `debuggable` flag is an important first step but does not fully protect the app from advanced attacks. Skilled attackers can enable debugging through various means, such as binary patching (see @MASTG-TECH-0038) to allow attachment of a debugger or the use of binary instrumentation tools like @MASTG-TOOL-0001 to achieve similar capabilities. For apps requiring a higher level of security, consider implementing anti-debugging techniques as an additional layer of defense. Refer to @MASWE-0101 for detailed guidance.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0015

---
title: Use `setRecentsScreenshotEnabled` to Prevent Screenshots When Backgrounded
alias: preventing-screenshots-when-backgrounded
id: MASTG-BEST-0015
platform: android
status: placeholder
note: Preventing screenshots when an app is backgrounded helps protect sensitive data from being exposed in system-generated snapshots used by the Recents screen.
---
OWASP Mobile Application Security Testing Guide: MASTG BEST 0038

---
title: Require Explicit User Confirmation for Biometric Authentication
alias: require-explicit-user-confirmation-for-biometric-authentication
id: MASTG-BEST-0038
platform: android
knowledge: [MASTG-KNOW-0001]
---

For sensitive operations requiring explicit user authorization (e.g., payments or access to health data), configure [`setConfirmationRequired(true)`](https://developer.android.com/reference/androidx/biometric/BiometricPrompt.PromptInfo.Builder#setConfirmationRequired(boolean)) in `BiometricPrompt.Builder`, or rely on the default behavior, which requires confirmation.

When `setConfirmationRequired(false)` is used, passive biometrics such as face recognition can authenticate the user implicitly as soon as the device detects their biometric data. This means authentication can complete without the user actively acknowledging the operation, which may not be appropriate for high-value actions.

The [Android documentation](https://developer.android.com/identity/sign-in/biometric-auth#no-explicit-user-action) notes that explicit confirmation provides assurance that the user intentionally initiated the sensitive operation, particularly when passive biometric modalities are used.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0008

---
title: Debugging Disabled for WebViews
alias: debugging-disabled-webviews
id: MASTG-BEST-0008
platform: android
knowledge: [MASTG-KNOW-0018]
---

Ensure that WebView debugging is disabled in production builds to prevent attackers from exploiting this feature to eavesdrop, modify, or debug communication within WebViews.

- Set `WebView.setWebContentsDebuggingEnabled` to `false` in production, or remove the calls entirely if they are unnecessary.
- If WebView debugging is required during development, ensure it is enabled only when the app is in a debuggable state by [checking the `ApplicationInfo.FLAG_DEBUGGABLE` flag at runtime](https://developer.chrome.com/docs/devtools/remote-debugging/webviews/#configure_webviews_for_debugging).

For example:

```kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
    { WebView.setWebContentsDebuggingEnabled(true); }
}
```

**Note:** Disabling WebView debugging this way helps protect an app already running on a device. For an attacker to exploit WebView debugging, they must have physical access to the device (e.g., a stolen or test device) or remote access through malware or other malicious means. Additionally, the device must typically be unlocked, and the attacker would need to know the device PIN, password, or biometric authentication to gain full control and connect debugging tools like @MASTG-TOOL-0004 or Chrome DevTools.

However, disabling WebView debugging does not eliminate all attack vectors. An attacker could:

1. Patch the app to add calls to these APIs (see @MASTG-TECH-0038), then repackage and re-sign it (see @MASTG-TECH-0039).
2. Use runtime method hooking (see @MASTG-TECH-0043) to enable WebView debugging dynamically at runtime.

Disabling WebView debugging serves as one layer of defense to reduce risks but should be combined with other security measures.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0036

---
title: Use Cryptographic Binding for Biometric Authentication
alias: use-cryptographic-binding-for-biometric-authentication
id: MASTG-BEST-0036
platform: android
knowledge: [MASTG-KNOW-0001]
---

For sensitive operations protected by biometric authentication, use [`BiometricPrompt.authenticate()`](https://developer.android.com/reference/androidx/biometric/BiometricPrompt#authenticate(androidx.biometric.BiometricPrompt.PromptInfo,androidx.biometric.BiometricPrompt.CryptoObject)) with a [`CryptoObject`](https://developer.android.com/reference/androidx/biometric/BiometricPrompt.CryptoObject) backed by an [Android Keystore](https://developer.android.com/privacy-and-security/keystore) key configured with `setUserAuthenticationRequired(true)`. This cryptographically binds the authentication result to the key operation, ensuring that the sensitive operation can only proceed after successful biometric verification.

Without a `CryptoObject`, authentication is event-bound and relies solely on the `onAuthenticationSucceeded` callback. This makes it susceptible to runtime logic manipulation, for example by hooking the callback to return success without actually passing biometric verification.

## Keystore Key Configuration

When generating the key with [`KeyGenParameterSpec.Builder`](https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder), configure:

- [`setUserAuthenticationRequired(true)`](https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)): requires the user to authenticate before the key can be used.
- [`setUserAuthenticationParameters(0, type)`](https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int,int)): a timeout of `0` requires authentication for every individual cryptographic operation. Avoid extended validity durations for sensitive operations, as the key remains usable for the entire validity window even if the device is later accessed by an unauthorized person.

!!! note
    [`setUserAuthenticationValidityDurationSeconds(int)`](https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserAuthenticationValidityDurationSeconds(int)) is deprecated from API level 30 in favor of `setUserAuthenticationParameters(int, int)`.
OWASP Mobile Application Security Testing Guide: MASTG BEST 0006

---
title: Use Up-to-Date APK Signing Schemes
alias: use-up-to-date-apk-signing-schemes
id: MASTG-BEST-0006
platform: android
knowledge: [MASTG-KNOW-0003]
---

Ensure that the app is signed with at least the v2 or v3 APK signing scheme, as these provide comprehensive integrity checks and protect the entire APK from tampering. For optimal security and compatibility, consider using v3, which also supports key rotation.

Optionally, you can add v4 signing to enable faster [incremental updates](https://developer.android.com/about/versions/11/features#incremental) in Android 11 and above, but v4 alone does not provide security protections and should be used alongside v2 or v3.

The signing configuration can be managed through Android Studio or the `signingConfigs` section in `build.gradle` or `build.gradle.kts`. To activate both the v3 and v4 schemes, the following values must be set:

```default
// build.gradle
android {
  ...
  signingConfigs {
    config {
        ...
        enableV3Signing true
        enableV4Signing true
    }
  }
}
```
OWASP Mobile Application Security Testing Guide: MASTG BEST 0030

---
title: Implementing Root Detection
alias: implementing-root-detection
id: MASTG-BEST-0030
platform: generic
knowledge: [MASTG-KNOW-0027]
---

Root detection is an environment risk signal that helps identify devices with elevated privilege or common rooting artifacts. It is a cost raising measure and it is bypassable, so it should be used only when rooted device risk materially impacts the app.

Apply the relevant root detection techniques described in @MASTG-KNOW-0027 based on the app's threat model and risk tolerance.

## Best Practices

1. **Layer defenses:** Pair root signals with integrity checks, anti debugging signals, and backend enforcement.
2. **Distribute checks:** Place checks near sensitive operations and session establishment, avoid a single centralized gate.
3. **Use multiple methods:** Combine filesystem artifacts, property checks, process checks, and native level checks.
4. **Avoid well-known patterns only:** Do not rely only on public signature lists or a single library default configuration.
5. **Use proportional responses:** Limit high risk operations first, add step up authentication, avoid full lockout when confidence is low.
6. **Validate server-side:** Use server policy to decide whether to allow transactions, based on risk and user context.
7. **Rotate and randomize:** Vary which checks run per session and per release, rotate indicators to reduce reusable bypass patches.

## Caveats and Considerations

Root detection is inherently bypassable through hooking and patching, and by hiding root artifacts. See @MASTG-TECH-0144.

Root detection can flag legitimate scenarios such as custom ROMs, enterprise test devices, and security research environments. Aggressive blocking can push users to modified app builds, and can increase support costs.
OWASP Mobile Application Security Testing Guide: index

---
hide: toc
title: Best Practices
---

??? info "About the MASTG Best Practices"

    The MASTG Best Practices are a collection of specific strategies and practices that can be used to prevent or mitigate security and privacy risks in mobile apps. 

    Each Best Practices is designed to be simple and focused and may apply to one or multiple tests in the MASTG.