flutter_security_suite
A Flutter plugin for mobile app security — root/jailbreak detection, emulator detection, screen recording detection, tamper detection, runtime protection, certificate pinning, app integrity, screenshot protection, and encrypted secure storage. Native implementations for Android (Kotlin) and iOS (Swift).
Features
| Feature | Android | iOS |
|---|---|---|
| Root / Jailbreak Detection | su binary & dangerous-app detection |
Cydia, dylib scan, writable-path check |
| Emulator Detection | Build props + QEMU device files | targetEnvironment(simulator) + env vars |
| Screen Recording Detection | DisplayManager presentation display check |
UIScreen.isCaptured (iOS 11+) |
| Tamper Detection | APK signing-cert presence + SHA-256 hash | Bundle ID mismatch + _CodeSignature check |
| Runtime Protection | Frida port, /proc/maps, Xposed, debugger |
Frida port, dylib scan, Frida env vars |
| Certificate Pinning | SHA-256 SPKI fingerprint | SHA-256 SPKI fingerprint |
| App Integrity | Debug flag & installer validation | Debugger detection via sysctl |
| Screenshot Protection | FLAG_SECURE window flag |
Secure UITextField overlay |
| Secure Storage | EncryptedSharedPreferences (AES-256) | iOS Keychain (SecItem API) |
Limitations & Security Considerations
- Root/jailbreak detection is heuristic. Advanced tooling such as Magisk with Zygisk modules can bypass file-based and package-based checks. This package provides a strong baseline, not a guarantee.
- Emulator detection on Android is heuristic. Build property spoofing can defeat it; the iOS Simulator check (
#if targetEnvironment(simulator)) is compile-time reliable. - Screen recording detection on Android detects mirroring/casting via virtual displays. Local file recording (e.g. the built-in screen recorder writing to MP4) cannot be reliably detected at the application level — use
FLAG_SECURE(screenshotProtection.enable()) as the primary mitigation. - Tamper detection catches unsophisticated repacking. A skilled attacker can re-sign an app and produce a valid
_CodeSignature. For stronger guarantees use Google Play Integrity API / Apple App Attest in addition to this package. - Runtime protection checks can themselves be hooked if Frida is already running. Layers of obfuscation and server-side attestation complement these checks.
- Certificate pinning is implemented in pure Dart over a raw
SecureSocket. It does not intercept traffic from native SDKs, WebViews, or third-party libraries that manage their own connections. - No active threat-intelligence feed. New bypass techniques will not be addressed automatically; update the package to get the latest checks.
Getting Started
Installation
dependencies:
flutter_security_suite: ^1.1.0
Platform Setup
Android — No additional setup required. Min SDK: 23.
iOS — Minimum deployment target: iOS 12.0. For jailbreak detection with the Cydia URL scheme, add to Info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>cydia</string>
</array>
Usage
Initialize
import 'package:flutter_security_suite/flutter_security_suite.dart';
final kit = SecureBankKit.initialize(
enableRootDetection: true,
enableAppIntegrity: true,
enableEmulatorDetection: true,
enableScreenRecordingDetection: false, // opt-in
enableTamperDetection: true,
enableRuntimeProtection: true,
enablePinning: false,
enableLogging: false,
certificatePins: {},
);
Run a Full Security Check
final status = await kit.runSecurityCheck();
if (status.isSecure) {
// All enabled checks passed — proceed normally.
} else {
if (status.isRooted) print('Device is rooted / jailbroken');
if (status.isEmulator) print('Running on emulator / simulator');
if (status.isScreenBeingRecorded) print('Screen is being recorded');
if (status.isTampered) print('App has been tampered with');
if (status.isRuntimeHooked) print('Runtime hooking framework detected');
if (!status.isAppIntegrityValid) print('App integrity check failed');
if (!status.isCertificatePinningValid) print('Certificate pinning failed');
}
Emulator Detection
final status = await kit.runSecurityCheck();
if (status.isEmulator) {
// Block automated attacks or reverse-engineering sessions.
}
Screen Recording Detection
final status = await kit.runSecurityCheck();
if (status.isScreenBeingRecorded) {
// Show warning overlay or temporarily hide sensitive content.
}
Tamper Detection
final status = await kit.runSecurityCheck();
if (status.isTampered) {
// APK / IPA has been re-signed or modified — terminate session.
}
One-time setup — discover your signing certificate hash:
// Run this once in a debug build to find your SHA-256 cert fingerprint.
final result = await kit.tamperDetection.getSignatureHash();
result.fold(
onSuccess: (hash) => print('Pin this in your config: $hash'),
onFailure: (e) => print('Error: ${e.message}'),
);
Runtime Protection
final status = await kit.runSecurityCheck();
if (status.isRuntimeHooked) {
// Frida / Xposed / debugger detected — abort sensitive operations.
}
Certificate Pinning
Pin the Subject Public Key Info (SPKI) SHA-256 hash. This survives certificate renewals as long as the key pair is unchanged.
final kit = SecureBankKit.initialize(
enablePinning: true,
certificatePins: {
'api.example.com': ['sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='],
},
);
Extract the SPKI pin from a live host:
openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
| openssl x509 -pubkey -noout \
| openssl pkey -pubin -outform DER \
| openssl dgst -sha256 -binary \
| base64
Screenshot Protection
await kit.screenshotProtection.enable();
await kit.screenshotProtection.disable();
Tip: Combine with screen recording detection. Enable protection to make the screen appear black in recordings even when
isScreenBeingRecordedistrue.
Secure Storage
await kit.secureStorage.write(key: 'auth_token', value: 'jwt_abc123');
final token = await kit.secureStorage.read(key: 'auth_token');
await kit.secureStorage.delete(key: 'auth_token');
await kit.secureStorage.deleteAll();
Error Handling
All operations return a SecurityResult<T>:
final result = await someSecurityOperation();
result.fold(
onSuccess: (data) => print('Result: $data'),
onFailure: (error) => print('Error: ${error.message}'),
);
// Or use the null-safe helper:
final value = result.dataOrNull;
SecurityStatus Fields
| Field | Type | Meaning |
|---|---|---|
isSecure |
bool |
true only when all enabled checks pass |
isRooted |
bool |
Device is rooted (Android) or jailbroken (iOS) |
isEmulator |
bool |
Running on an emulator or iOS Simulator |
isScreenBeingRecorded |
bool |
Screen is being captured or mirrored |
isTampered |
bool |
App bundle / APK shows signs of tampering |
isRuntimeHooked |
bool |
Frida / Xposed / debugger is active |
isAppIntegrityValid |
bool |
App is not debuggable and from a trusted source |
isCertificatePinningValid |
bool |
TLS certificate matches the pinned SPKI hash |
Architecture
┌─────────────────────────────────────────────┐
│ PUBLIC API (SecureBankKit) │ Consumer-facing facade
├─────────────────────────────────────────────┤
│ DOMAIN (Entities, UseCases, Repositories) │ Business logic & contracts
├─────────────────────────────────────────────┤
│ DATA (Datasources, Repository Impls) │ Implementation layer
├─────────────────────────────────────────────┤
│ PLATFORM (MethodChannel Bridge) │ Flutter ↔ Native bridge
├─────────────────────────────────────────────┤
│ CORE (Result types, Exceptions, Logger) │ Shared utilities
└─────────────────────────────────────────────┘
How It Works
Root / Jailbreak Detection
Android: Scans system paths for su binaries, detects rooting apps via PackageManager (SuperSU, Magisk, etc.), checks build tags for test-keys.
iOS: Checks for Cydia/jailbreak files, scans loaded dylibs for Substrate/Frida/Cycript, tests Cydia URL scheme, attempts writes to restricted /private/ paths.
Emulator Detection
Android: Inspects Build.FINGERPRINT, Build.MODEL, Build.HARDWARE (goldfish/ranchu), Build.MANUFACTURER (Genymotion) and QEMU-specific device files.
iOS: Compile-time #if targetEnvironment(simulator) flag plus runtime check of Simulator-specific environment variables (SIMULATOR_DEVICE_NAME, SIMULATOR_UDID).
Screen Recording Detection
iOS: UIScreen.main.isCaptured returns true when the screen is recorded via ReplayKit, mirrored via AirPlay, or captured via QuickTime/Xcode USB.
Android: DisplayManager.getDisplays(DISPLAY_CATEGORY_PRESENTATION) — non-empty means a virtual display exists for casting/mirroring.
Tamper Detection
Android: Verifies the APK signing certificate is present via PackageManager.GET_SIGNING_CERTIFICATES. Exposes getSigningCertificateHash() (SHA-256 hex) for custom certificate pinning.
iOS: Checks Bundle.bundleIdentifier matches CFBundleIdentifier in Info.plist, and verifies the _CodeSignature/ directory exists in the app bundle.
Runtime Protection
Both platforms: Attempts TCP connection to Frida server port 27042; scans loaded dylibs / /proc/self/maps for Frida strings; checks Xposed framework files (Android); checks Frida environment variables (iOS); detects attached debugger.
App Integrity
Android: Verifies FLAG_DEBUGGABLE is absent and installer is a trusted store (Google Play, Amazon, Huawei).
iOS: Detects debugger via sysctl P_TRACED flag. isAppStoreBuild() additionally checks for absence of embedded.mobileprovision.
Certificate Pinning
Pins the SHA-256 SPKI fingerprint. Verified in Dart before the HTTP request body is sent. Survives certificate renewal if the key pair is unchanged.
Secure Storage
Android: EncryptedSharedPreferences — AES-256-SIV key encryption, AES-256-GCM value encryption.
iOS: Keychain via SecItem API — accessibility kSecAttrAccessibleWhenUnlockedThisDeviceOnly.
Project Structure
flutter_security_suite/
├── lib/
│ ├── flutter_security_suite.dart # Main export
│ ├── secure_bank_kit.dart # Public API facade
│ ├── core/ # SecurityResult, exceptions, logger
│ ├── domain/
│ │ ├── entities/security_status.dart # SecurityStatus (7 fields)
│ │ ├── repositories/ # 9 repository contracts
│ │ └── usecases/ # 9 use cases
│ ├── data/
│ │ ├── datasources/ # 9 datasources
│ │ └── repositories_impl/ # 9 repository implementations
│ └── platform/
│ └── method_channel_security.dart # MethodChannel bridge
├── android/src/main/kotlin/ # 8 Kotlin native handlers
├── ios/.../Sources/ # 8 Swift native handlers
├── example/ # Demo application
└── test/ # Unit tests
Testing
flutter test
Tests cover platform (MethodChannel mocks), domain (use cases with mocked repositories), and data (repository impls with mocked datasources) layers — both success and failure paths.
Requirements
| Minimum | |
|---|---|
| Flutter | >= 3.10.0 |
| Dart SDK | >= 3.0.0 |
| Android | API 23 (Marshmallow) |
| iOS | 12.0 |
Alternatives
- flutter_jailbreak_detection — focused solely on root/jailbreak
- flutter_secure_storage — encrypted key-value storage only
- ssl_pinning_plugin — certificate pinning only
This package provides a broader security baseline in a single dependency.
Contributing
Contributions and bug reports are welcome. Please open an issue before submitting a large pull request.
License
MIT — see LICENSE.
Libraries
- core/exceptions/security_exception
- core/result/security_result
- core/utils/logger
- data/datasources/app_integrity_datasource
- data/datasources/certificate_pinning_datasource
- data/datasources/emulator_detection_datasource
- data/datasources/root_detection_datasource
- data/datasources/runtime_protection_datasource
- data/datasources/screen_recording_datasource
- data/datasources/screenshot_protection_datasource
- data/datasources/secure_storage_datasource
- data/datasources/tamper_detection_datasource
- data/repositories_impl/app_integrity_repository_impl
- data/repositories_impl/certificate_pinning_repository_impl
- data/repositories_impl/emulator_detection_repository_impl
- data/repositories_impl/root_detection_repository_impl
- data/repositories_impl/runtime_protection_repository_impl
- data/repositories_impl/screen_recording_repository_impl
- data/repositories_impl/screenshot_protection_repository_impl
- data/repositories_impl/secure_storage_repository_impl
- data/repositories_impl/tamper_detection_repository_impl
- domain/entities/security_status
- domain/repositories/app_integrity_repository
- domain/repositories/certificate_pinning_repository
- domain/repositories/emulator_detection_repository
- domain/repositories/root_detection_repository
- domain/repositories/runtime_protection_repository
- domain/repositories/screen_recording_repository
- domain/repositories/screenshot_protection_repository
- domain/repositories/secure_storage_repository
- domain/repositories/tamper_detection_repository
- domain/usecases/check_app_integrity_usecase
- domain/usecases/check_emulator_usecase
- domain/usecases/check_root_status_usecase
- domain/usecases/check_runtime_protection_usecase
- domain/usecases/check_screen_recording_usecase
- domain/usecases/check_tamper_usecase
- domain/usecases/secure_storage_usecase
- domain/usecases/toggle_screenshot_protection_usecase
- domain/usecases/validate_certificate_usecase
- flutter_security_suite
- SecureBankKit – Enterprise-grade Flutter security plugin.
- platform/method_channel_security
- secure_bank_kit