Skip to content

MASTG-DEMO-0028: Uses of KeyguardManager.isDeviceSecure and BiometricManager.canAuthenticate with semgrep

Download MASTG-DEMO-0028 APK Open MASTG-DEMO-0028 Folder Build MASTG-DEMO-0028 APK

Sample

This sample checks if the device has a secure lock screen via KeyguardManager.isDeviceSecure and if the device supports strong biometric authentication using BiometricManager.canAuthenticate.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.owasp.mastestapp

import android.app.KeyguardManager
import android.content.Context
import android.hardware.biometrics.BiometricManager
import android.os.Build

class MastgTest(private val context: Context) {
    fun mastgTest(): String {
        val isLocked = isDeviceSecure(context)
        val biometricStatus = checkStrongBiometricStatus()
        return "Device has a passcode: $isLocked\n\n" +
                "Biometric status: $biometricStatus"
    }

    /**
     * Checks if the device has a secure lock screen (e.g., PIN, pattern, password).
     *
     * @return `true` if the device has a secure lock screen, `false` otherwise.
     */

    fun isDeviceSecure(context: Context): Boolean {
        val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
        return keyguardManager.isDeviceSecure
    }

    /**
     * Checks if the device supports strong biometric authentication (e.g., fingerprint, face, iris)
     * and if the user has enrolled biometric credentials.
     *
     * **Note:** This API is available on API level 30 (Android R) and above.
     *
     * @return A human-readable string describing the biometric status.
     */
    fun checkStrongBiometricStatus(): String {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val biometricManager = context.getSystemService(BiometricManager::class.java)
            val result = biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
            return when (result) {
                BiometricManager.BIOMETRIC_SUCCESS ->
                    "BIOMETRIC_SUCCESS - Strong biometric authentication is available."
                BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
                    "BIOMETRIC_ERROR_NO_HARDWARE - No biometric hardware available."
                BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
                    "BIOMETRIC_ERROR_HW_UNAVAILABLE - Biometric hardware is currently unavailable."
                BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED ->
                    "BIOMETRIC_ERROR_NONE_ENROLLED - No biometrics enrolled."
                else ->
                    "Unknown biometric status: $result"
            }
        } else {
            return "Strong biometric authentication check is not supported on this API level."
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.owasp.mastestapp;

import android.app.KeyguardManager;
import android.content.Context;
import android.hardware.biometrics.BiometricManager;
import android.os.Build;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;

/* compiled from: MastgTest.kt */
@Metadata(d1 = {"\u0000 \n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\u000b\n\u0002\b\u0002\b\u0007\u0018\u00002\u00020\u0001B\r\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0002\u0010\u0004J\u0006\u0010\u0005\u001a\u00020\u0006J\u000e\u0010\u0007\u001a\u00020\b2\u0006\u0010\u0002\u001a\u00020\u0003J\u0006\u0010\t\u001a\u00020\u0006R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000¨\u0006\n"}, d2 = {"Lorg/owasp/mastestapp/MastgTest;", "", "context", "Landroid/content/Context;", "(Landroid/content/Context;)V", "checkStrongBiometricStatus", "", "isDeviceSecure", "", "mastgTest", "app_debug"}, k = 1, mv = {1, 9, 0}, xi = 48)
/* loaded from: classes4.dex */
public final class MastgTest {
    public static final int $stable = 8;
    private final Context context;

    public MastgTest(Context context) {
        Intrinsics.checkNotNullParameter(context, "context");
        this.context = context;
    }

    public final String mastgTest() {
        boolean isLocked = isDeviceSecure(this.context);
        String biometricStatus = checkStrongBiometricStatus();
        return "Device has a passcode: " + isLocked + "\n\nBiometric status: " + biometricStatus;
    }

    public final boolean isDeviceSecure(Context context) {
        Intrinsics.checkNotNullParameter(context, "context");
        Object systemService = context.getSystemService("keyguard");
        Intrinsics.checkNotNull(systemService, "null cannot be cast to non-null type android.app.KeyguardManager");
        KeyguardManager keyguardManager = (KeyguardManager) systemService;
        return keyguardManager.isDeviceSecure();
    }

    public final String checkStrongBiometricStatus() {
        if (Build.VERSION.SDK_INT >= 30) {
            BiometricManager biometricManager = (BiometricManager) this.context.getSystemService(BiometricManager.class);
            int result = biometricManager.canAuthenticate(15);
            switch (result) {
                case 0:
                    return "BIOMETRIC_SUCCESS - Strong biometric authentication is available.";
                case 1:
                    return "BIOMETRIC_ERROR_HW_UNAVAILABLE - Biometric hardware is currently unavailable.";
                case 11:
                    return "BIOMETRIC_ERROR_NONE_ENROLLED - No biometrics enrolled.";
                case 12:
                    return "BIOMETRIC_ERROR_NO_HARDWARE - No biometric hardware available.";
                default:
                    return "Unknown biometric status: " + result;
            }
        }
        return "Strong biometric authentication check is not supported on this API level.";
    }
}

Steps

Let's run semgrep rules against the sample code.

../../../../rules/mastg-android-device-passcode-present.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
rules:
  - id: mastg-android-device-passcode-present
    languages:
      - java
    severity: INFO
    metadata:
      summary: This rule searches for API that checks whether the device passcode is set.
    message: "[MASVS-STORAGE] Make sure to verify that your app runs on a device with a passcode set"
    pattern-either:
      - pattern: |
          $X.getSystemService("keyguard");
          ...
          $Y.isDeviceSecure();
      - pattern: |
          BiometricManager $BM = (BiometricManager) $X.getSystemService(BiometricManager.class);
          ...
          $BM.canAuthenticate($VAL);
run.sh
1
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-device-passcode-present.yml ./MastgTest_reversed.java --text -o output.txt

Observation

The output shows all usages of APIs related to secure screen lock detection.

output.txt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
┌─────────────────┐
 2 Code Findings 
└─────────────────┘

    MastgTest_reversed.java
      rules.mastg-android-device-passcode-present
          [MASVS-STORAGE] Make sure to verify that your app runs on a device with a passcode set

           30 Object systemService = context.getSystemService("keyguard");
           31 Intrinsics.checkNotNull(systemService, "null cannot be cast to non-null type
               android.app.KeyguardManager");                                              
           32 KeyguardManager keyguardManager = (KeyguardManager) systemService;
           33 return keyguardManager.isDeviceSecure();
            ⋮┆----------------------------------------
           38 BiometricManager biometricManager = (BiometricManager)
               this.context.getSystemService(BiometricManager.class);
           39 int result = biometricManager.canAuthenticate(15);

Evaluation

The test passes because the output shows references to APIs that check for secure screen lock presence, specifically:

  • KeyguardManager.isDeviceSecure in line 33
  • BiometricManager.canAuthenticate in line 39