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).

pub.dev License: MIT Platform


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 isScreenBeingRecorded is true.

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

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