Introduction
We express our gratitude to the Perawallet team for the collaborative engagement that enabled the execution of this dApp Security Assessment.
Pera Wallet is a non custodial, self custody wallet for the Algorand blockchain, enabling users to create or import accounts and manage algos, Algorand standard assets, and NFTs entirely from their own device. The wallet supports legacy 25 word Algorand mnemonics, BIP-39/HD wallets, Algorand standard backup exports, watch only accounts and hardware backed accounts via Ledger, alongside native ALGO staking, multisignature (M-of-N) accounts, a debit card product (Pera Card), WalletConnect based connectivity to third-party Algorand dApps, and a rekeying system for changing an account's signing authority without changing its address.
Document | |
|---|---|
| Name | dApp Code Review and Security Analysis Report for Perawallet |
| Audited By | Adedolapo Olayinka-Adeyemi |
| Approved By | Faizan Nehal |
| Website | perawallet.app |
| Changelog | 1/09/2026 - Preliminary Report |
| 19/10/2026 - Final Report | |
| Platform | Blockchain |
| Language | Typescript |
| Tags | White-Box |
| Methodology | https://docs.hacken.io/methodologies/dapp-audit-methodology→ |
Document
- Name
- dApp Code Review and Security Analysis Report for Perawallet
- Audited By
- Adedolapo Olayinka-Adeyemi
- Approved By
- Faizan Nehal
- Website
- perawallet.app
- Changelog
- 1/09/2026 - Preliminary Report
- 19/10/2026 - Final Report
- Platform
- Blockchain
- Language
- Typescript
- Tags
- White-Box
Review Scope | |
|---|---|
| Repository | https://github.com/perawallet/pera-react-native , https://github.com/algorandfoundation/react-native-passkey-autofill, https://github.com/algorandfoundation/wallet-provider-extensions, https://github.com/algorandfoundation/wallet-provider→ |
| Commit | c2d1ef090 , cf5a8cf (canary.22), 149ef2a (canary.17 / .13 tags), 53e22e4 (canary.5) |
Review Scope
- Commit
- c2d1ef090 , cf5a8cf (canary.22), 149ef2a (canary.17 / .13 tags), 53e22e4 (canary.5)
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
{FindingsVulnSeverityStatusTable}
Test coverage
Branch coverage across the four in-scope repositories ranges from the high 60s to 100% per package, with most security relevant packages between 80–97%.
Deployment and basic user interactions are covered with tests.
Negative case coverage is present and substantive.
Dedicated tests for fail safe behaviours such as master key unavailable handling, relying party-ID scoping and WebAuthn user verification gating.
System Overview
Pera React Native:
Pera-react-native is an Expo managed React Native monorepo implementing the Pera Wallet mobile app for iOS and Android, layered as apps/mobile (UI), packages/* (business logic), and extensions/* (platform abstractions). The entry point, apps/mobile/index.js, installs crypto polyfills and registers App.tsx, which wires crash reporting, hydrates the keystore, and mounts the authenticated navigation tree behind an error boundary.
apps/mobile — the app shell and screens: bootstrap and navigation (index.js/App.tsx/RootComponent.tsx/routes), a deep-link/QR-parsing surface reachable via QR codes, clipboard, and universal links, a security module (PIN/biometric gating plus a duress PIN that silently wipes and replaces the wallet under coercion), an in-app WebView bridge that re-validates page origin and a per-mount token on every message, and the WalletConnect, signing, onboarding, backup, rekey, ledger, and multisig screens, each thin over its corresponding package.
packages/* — the business logic: kms is the private-key custody core (seed/PRF derivation, domain-scoped access control, secret zeroing); security holds the PIN and duress-PIN hashing (PBKDF2-SHA256, constant-time compare); signing is the sign-request pipeline (mandatory approval gate, per-channel transports, transaction-integrity validators); blockchain, walletconnect, hardware-wallet/ledger, and multisig cover Algorand SDK integration, WalletConnect v1 session management, hardware-signer address confirmation, and M-of-N coordination; backup covers ARC-35, Pera Web, and mnemonic account recovery; database and migrate cover local persistence and legacy-app migration (including a native iOS Keychain reader); app-integrity, card, and shared cover device attestation, the Pera Card integration (tokens kept only in the encrypted keystore), and the app-wide logger's secret-redaction layer. Remaining packages (assets, accounts, settings, and similar) follow the same layering with lighter security relevance.
extensions/* — platform abstractions: provider is the composition root that assembles the runtime provider object; platform and platform-react-native define and implement the platform services (certificate pinning, strong-only biometrics, MMKV storage, Crashlytics/remote config); passkey-autofill is a façade over the native passkey module.
Wallet-provider:
wallet-provider is a small, dependency free package providing the base Provider class and extension composition mechanism every other repository in this engagement builds on. It holds no runtime secrets, network client, or native code.
src/types.ts defines the Provider constructor and withExtensions()
src/crypto.ts provides local non-key utilities (CSPRNG-backed IDs, buffer clearing)
src/index.ts is the export-only entry point.
Wallet Provider Extensions:
wallet-provider-extensions handles wallet key custody, account/identity record-keeping, and shared logging, as a set of extension packages that each compose onto a wallet-provider Provider via a store/extension/keystore-extension layout. The security critical piece is keystore/store (the platform independent key generation, signing, and encryption core) and keystore/react-native (the React Native implementation pera-react-native's key management is built on, deriving at rest encryption from a Keychain-backed random master key and persisting to MMKV). accounts/ and identities/ manage the account list and DID-based identities on top of the keystore extension; log/ is a shared logging store; build/ is this monorepo's own release tooling.
React Native Passkey Autofill:
react-native-passkey-autofill provides the native Android Credential Manager and iOS AutoFill Credential Provider integration for Algorand Liquid Auth passkeys, exposed to JavaScript via an Expo native module (src/index.ts) and wired into a consuming app by app.plugin.js.
Android :
CreatePasskeyActivity.kt/GetPasskeyActivity.kt implement the WebAuthn create/get ceremonies
PasskeyAutofillCredentialProviderService.kt answers the OS's credential queries
CredentialRepository.kt persists encrypted credential records
WebAuthn.kt injects a configured AAGUID to match iOS/legacy authenticator identity
Prf.kt derives each credential's PRF secret from the wallet's HD root, RP id, and user handle.
iOS :
CredentialProviderViewController.swift is the AutoFill extension's entry point
PasskeyCredentialStore.swift is the Keychain backed analog of the Android repository
WebAuthn.swift and Prf.swift mirror the Android attestation/PRF logic.
Findings
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2026-1897 | Generic keystore encryption derives its secret from the public key | fixed | High | |
| F-2026-1899 | Android responses assert WebAuthn UV when no verification occurred | fixed | Medium | |
| F-2026-1899 | iOS Credential-Extension Crypto Dependency Resolves From a Mutable Swift Package Branch | fixed | Medium | |
| F-2026-1909 | Keystore Hydration Silently Skips Corrupted Records and Can Retain Stale Reactive State | mitigated | Medium | |
| F-2026-1907 | Android clearCredentials Clears the Wallet's Entire Shared Keystore Namespace — Medium | fixed | Medium | |
| F-2026-1906 | Android Deterministic Passkey Derivation Uses user.name Instead of the Stable WebAuthn User Handle | accepted | Medium | |
| F-2026-1960 | WalletConnect v1 session secrets are persisted in MMKV without application-layer encryption | fixed | Medium | |
| F-2026-1959 | Stale WalletConnect session updates can restore removed sessions and discard newer connections | fixed | Medium | |
| F-2026-1898 | Android passkey creation stores private keys as encoded plaintext when the mirrored master key is unavailable | fixed | Low | |
| F-2026-1916 | Provider Extension Composition Permits Silent Overwrite of Provider Properties | accepted | Low |
Appendix 1. Severity Definitions
Findings are categorized based on their potential impact and assigned a severity level using the Common Vulnerability Scoring System (CVSS) version 4.0: →
Severity | Description |
|---|---|
Critical | These issues present a major security vulnerability that poses a severe risk to the system. They require immediate attention and must be resolved to prevent a potential security breach or other significant harm. |
High | These issues present a significant risk to the system, but may not require immediate attention. They should be addressed in a timely manner to reduce the risk of the potential security breach. |
Medium | These issues present a moderate risk to the system and cannot have a great impact on its function. They should be addressed in a reasonable time frame, but may not require immediate attention. |
Low | These issues present no risk to the system and typically relate to the code quality problems or general recommendations. They do not require immediate attention and should be viewed as a minor recommendation. |
Severity
- Critical
Description
- These issues present a major security vulnerability that poses a severe risk to the system. They require immediate attention and must be resolved to prevent a potential security breach or other significant harm.
Severity
- High
Description
- These issues present a significant risk to the system, but may not require immediate attention. They should be addressed in a timely manner to reduce the risk of the potential security breach.
Severity
- Medium
Description
- These issues present a moderate risk to the system and cannot have a great impact on its function. They should be addressed in a reasonable time frame, but may not require immediate attention.
Severity
- Low
Description
- These issues present no risk to the system and typically relate to the code quality problems or general recommendations. They do not require immediate attention and should be viewed as a minor recommendation.
Appendix 2. Scope
The scope of the project includes the following from the provided repository:
Scope Details | |
|---|---|
| Repository | https://github.com/perawallet/pera-react-native , https://github.com/algorandfoundation/react-native-passkey-autofill, https://github.com/algorandfoundation/wallet-provider-extensions, https://github.com/algorandfoundation/wallet-provider→ |
| Commit | c2d1ef090 , cf5a8cf (canary.22), 149ef2a (canary.17 / .13 tags), 53e22e4 (canary.5) |
Scope Details
- Commit
- c2d1ef090 , cf5a8cf (canary.22), 149ef2a (canary.17 / .13 tags), 53e22e4 (canary.5)
Appendix 3. Additional Valuables
Frameworks and Methodologies
This security assessment was conducted in alignment with recognised penetration testing standards, methodologies and guidelines, including the NIST SP 800-115 – Technical Guide to Information Security Testing and Assessment →, the Penetration Testing Execution Standard (PTES) →, and the OWASP Testing Guide →. These assets provide a structured foundation for planning, executing, and documenting technical evaluations such as vulnerability assessments, exploitation activities, and security code reviews. Hacken’s internal penetration testing methodology extends these principles to Web2 and Web3 environments to ensure consistency, repeatability, and verifiable outcomes.