Status: pre-launch. This evidence reflects implemented code and deployed infrastructure. Provii is not yet serving end-user production traffic, so production operational metrics and audit history are not yet available.
Mobile Security Evidence Collection
Control Coverage: OWASP MASVS 2.0, ISMS UC-044 through UC-051 Date Generated: 15 February 2026 Status: Complete Repository Analysed: Provii mobile wallet (client) repository under the MaelstromAI GitHub enterprise (iOS: Swift/SwiftUI, Android: Kotlin/Jetpack Compose)
Executive Summary
The Provii Wallet mobile application implements defence-in-depth security across both iOS and Android platforms. All sensitive data uses platform-native secure storage (iOS Keychain, Android Keystore + EncryptedSharedPreferences). Biometric authentication is bound to cryptographic operations. The app includes jailbreak/root detection, app integrity verification, screenshot blocking, constant-time PIN comparison, and memory zeroisation of sensitive data. CI runs 7 security scanning jobs (Gitleaks, Zizmor, Semgrep, CodeQL Swift, CodeQL Kotlin, dependency check, mobile-specific checks) on every push and PR.
Data Protection (MASVS-STORAGE)
iOS: Keychain with Biometric Protection
File: ios/ProviiWallet/ProviiWallet/Core/Services/KeychainService.swift
- All sensitive data stored via iOS Keychain with
kSecAttrAccessibleWhenUnlockedThisDeviceOnly - Biometric protection via
SecAccessControlCreateWithFlagswith.biometryCurrentSet. re-enrolment invalidates keys kSecAttrIsExtractable: kCFBooleanFalseprevents key export- Secure Enclave key generation available for devices that support it (
generateSecureEnclaveKey) - PBKDF2-SHA256 with 10,000 rounds for PIN derivation
- Constant-time comparison for PIN verification (prevents timing attacks)
- Rate limiting on PIN attempts with lockout (
RateLimiterintegration)
Android: Keystore + EncryptedSharedPreferences
File: android/app/src/main/java/com/provii/wallet/security/NativeKeystoreManager.kt
- AES-256-GCM via Android Keystore (
AndroidKeyStoreprovider) setUserAuthenticationRequired(true)with 30-second validity windowAUTH_BIOMETRIC_STRONG | AUTH_DEVICE_CREDENTIALauthentication requirement- StrongBox backing on Android P+ devices (
setIsStrongBoxBacked(true)) - EncryptedSharedPreferences with AES256-SIV (key encryption) and AES256-GCM (value encryption)
- Master key rotation support (
rotateMasterKey()) ByteArray.zeroize()extension clears sensitive data from memory after encryption
Secure Preferences (Android)
File: android/app/src/main/java/com/provii/wallet/security/SecurePreferencesManager.kt
- MASVS-CODE-1 compliant: replaces plain SharedPreferences with EncryptedSharedPreferences
- Separate preference files for general settings and session state
- Deep link state automatically expires after 5 minutes
clearSessionState()andclearAll()for secure logout
Authentication (MASVS-AUTH)
Biometric Authentication
File: ios/ProviiWallet/ProviiWallet/Core/Services/BiometricService.swift
- MASVS AUTH-2: Context reuse limited to 5 seconds (not system default)
- MASVS AUTH-2:
authenticateWithKeyBindingbinds biometric auth to Secure Enclave cryptographic operation - MASVS AUTH-2: Context invalidated on logout (
invalidateContext()) - All biometric events audit-logged (success, failure, context invalidation)
- Face ID and Touch ID support with accessibility-friendly descriptions
PIN Verification
File: ios/ProviiWallet/ProviiWallet/Core/Services/KeychainService.swift
- PIN stored as PBKDF2-derived key, never in plaintext
- Constant-time comparison prevents timing side-channel attacks
- Rate limiter with progressive lockout (tracks remaining attempts)
- Failed attempts and lockouts logged to audit trail
Cryptography (MASVS-CRYPTO)
iOS
File: ios/ProviiWallet/ProviiWallet/Core/Services/CryptoUtils.swift
- AES-256-GCM via Apple CryptoKit (
AES.GCM.seal/AES.GCM.open) - 12-byte IV, 128-bit GCM tag
SecRandomCopyBytesfor key generation (cryptographically secure)- Base64url encoding/decoding for credential transport
- PIN key derivation: PBKDF2-HMAC-SHA256, 10,000 rounds, 32-byte salt
Android
File: android/app/src/main/java/com/provii/wallet/security/NativeKeystoreManager.kt
- AES-256-GCM via Android Keystore (
AES/GCM/NoPadding) - 128-bit GCM tag length
- Hardware-backed key generation (StrongBox where available)
- Input data zeroised after encryption (
ByteArray.zeroize())
Memory Protection
File: ios/ProviiWallet/ProviiWallet/Core/Security/SecureString.swift
SecureStringclass overwrites memory buffer with zeros on deallocation- Uses
memsetonUnsafeMutableBytesfor reliable memory clearing deinitis designed to perform cleanup even ifclear()is not explicitly called
App Integrity (MASVS-RESILIENCE)
Jailbreak Detection (iOS)
File: ios/ProviiWallet/ProviiWallet/Core/Security/JailbreakDetector.swift
Six detection methods:
- Jailbreak file path checks (Cydia, Sileo, Zebra, ssh, MobileSubstrate, etc.)
- Sandbox integrity verification (write test to restricted path)
- Suspicious app detection
- Write access to restricted directories
- Symbolic link detection
- Dynamic library injection detection (MachO inspection)
Skipped on simulator builds (#if targetEnvironment(simulator)).
Root Detection (Android)
File: android/app/src/main/java/com/provii/wallet/security/integrity/RootDetector.kt
MASVS-RESILIENCE-3 compliant. All-local detection (no Google Play Integrity API dependency):
subinary detection across common paths- Root management app detection (Magisk, SuperSU, KingRoot)
- Build property checks (test-keys, debuggable)
- Dangerous system properties
- BusyBox detection
- SELinux enforcement status
- Emulator detection
Structured result with isRooted and isCompromisedEnvironment flags.
APK Signature Verification (Android)
File: android/app/src/main/java/com/provii/wallet/security/integrity/SignatureVerifier.kt
MASVS-RESILIENCE-2 compliant:
- APK signature hash verification
classes.dexhash verification- AndroidManifest integrity check
- Package name validation
- Installer verification (Play Store / trusted source)
App Integrity (iOS)
File: ios/ProviiWallet/ProviiWallet/Core/Security/IntegrityChecker.swift
- Bundle code signature verification (
_CodeSignaturedirectory) - Executable integrity check
- Provisioning profile verification
- Resource hash computation (SHA-256 via CryptoKit)
Screen Capture Protection
iOS
File: ios/ProviiWallet/ProviiWallet/Core/Security/ScreenshotBlocker.swift
- Uses
UITextField.isSecureTextEntrytechnique to block screenshots of sensitive views - Screen recording detection via
UIScreen.main.isCaptured - SwiftUI
ScreenshotBlockingModifierfor declarative usage - Screenshot and recording attempts logged as critical security events
Android
File: android/app/src/main/java/com/provii/wallet/MainActivity.kt
WindowManager.LayoutParams.FLAG_SECUREset on activity window- Prevents screenshots and screen recording system-wide for the app
Code Shrinking
Android
File: android/app/build.gradle.kts (line 97)
- R8 enabled for release builds (
isMinifyEnabled = true) to remove unused code and reduce APK size - Uses
proguard-android-optimise.txtbaseline plus customproguard-rules.pro - Not used for obfuscation. the codebase is open source
Security Audit Logging
File: ios/ProviiWallet/ProviiWallet/Core/Services/AuditLogger.swift
audit trail using Apple’s unified logging system:
| Event Category | Events Logged |
|---|---|
| Authentication | WebAuthn success/failure, YubiKey success/failure |
| Biometric | Auth success/failure, context invalidation |
| PIN | Verification failure, lockout |
| Credentials | Issuance, blind attestation, expiry, revocation |
| Verification | Proof generation, verification result |
| Security Violations | Tampering, jailbreak, debugger, invalid signature |
| Screen Capture | Screenshot attempt, screen recording attempt |
| Storage | Keychain access (save/read/delete per key) |
| Deep Links | Received, processed, fallback |
Three severity levels: info, warning, critical. Critical events trigger sendToSecurityMonitoring.
Privacy annotations: officer IDs logged as .public, credential IDs as .private.
CI Security Pipeline
File: .github/workflows/security-audit.yml
Runs on every push/PR to main + weekly schedule (Monday 02:00 UTC).
| Job | Tool | Scope |
|---|---|---|
| Secret Detection | Gitleaks v2.3.8 | Full repo history |
| Workflow Security | Zizmor v0.4.1 | GitHub Actions workflows |
| SAST | Semgrep | Swift, Kotlin, Android, iOS, OWASP Top 10, secrets |
| Deep Analysis (Swift) | CodeQL v3.28.6 | Swift source with security-and-quality queries |
| Deep Analysis (Kotlin) | CodeQL v3.28.6 | Kotlin source with security-and-quality queries |
| Dependency Check | Gradle + CocoaPods | Release classpath dependencies |
| Mobile Security | Custom scripts | Hardcoded secrets, Android manifest, iOS ATS, insecure HTTP |
| License Compliance | Gradle + CocoaPods | Dependency license audit |
All actions SHA-pinned. Harden-runner (step-security v2.14.1) on all jobs. Permissions scoped to contents: read + security-events: write.
Transport Security
- iOS. App Transport Security (ATS) enforced. all connections require TLS
- Android. Network Security Config with
cleartextTrafficPermitted="false"(default for targetSdk 28+) - All API endpoints are HTTPS only (Cloudflare-terminated TLS 1.3)
Summary of MASVS Coverage
| MASVS Category | Status | Key Controls |
|---|---|---|
| MASVS-STORAGE | Implemented | iOS Keychain, Android Keystore + EncryptedSharedPreferences, memory zeroisation |
| MASVS-CRYPTO | Implemented | AES-256-GCM, PBKDF2, Secure Enclave, StrongBox, constant-time comparison |
| MASVS-AUTH | Implemented | Biometric with crypto binding, PIN rate limiting, 5s context reuse |
| MASVS-NETWORK | Implemented | TLS enforcement (ATS + Cloudflare TLS 1.3), no cleartext traffic |
| MASVS-PLATFORM | Implemented | Deep link validation, 5-minute state expiry, secure intent handling |
| MASVS-CODE | Implemented | R8 code shrinking, no debug flags in release, secure error handling |
| MASVS-RESILIENCE | Implemented | Jailbreak/root detection (6+ checks each), APK signature verification, screenshot blocking |