flutter_shield 1.2.0
flutter_shield: ^1.2.0 copied to clipboard
A comprehensive device security and vulnerability detection package for Flutter — Android, iOS, Web, Windows, Linux, and macOS.
Flutter Shield 🛡️ #
A comprehensive device security and vulnerability detection package for Flutter — Android & iOS.
Overview #
Flutter Shield gives you a single, unified API to detect 33+ security vulnerabilities across Android and iOS — from root/jailbreak and Magisk detection to Firebase App Check attestation. Run a full scan in one call or cherry-pick individual checks for targeted enforcement.
Demo & Screenshots #
| Demo | Home Screen | Scan Results |
|---|---|---|
![]() |
![]() |
![]() |
Table of Contents #
- Features
- Installation
- Platform Setup
- Firebase App Check Setup
- Quick Start
- Usage
- API Reference
- Security Categories
- Best Practices
- Platform Differences
- Limitations
- Contributing
- License
Features #
Flutter Shield covers 33+ security checks across 8 categories — all returned as typed, structured results.
| Category | Checks | Description |
|---|---|---|
| 🔒 Device Integrity | 5 | Root, jailbreak, Magisk, emulator, debug, malware |
| 🗄️ Storage Security | 6 | Local storage, plaintext, keychain, file permissions |
| 🔑 Authentication | 3 | Biometrics, bypass, screen lock |
| 🖥️ UI Security | 6 | Screenshot, recording, clipboard, overlay, background |
| 📡 Communication | 4 | IPC, intent hijacking, broadcast receivers, deep links |
| 🌐 WebView | 2 | Debugging, JavaScript interface |
| ⚙️ Permissions & Runtime | 3 | Runtime permissions, autofill, sensor abuse |
| 🔬 Other | 2 | Device time trust, side-channel attacks |
| 🛡️ App Attestation | 2 | Play Integrity API token, Firebase App Check |
Installation #
Add Flutter Shield to your pubspec.yaml:
dependencies:
flutter_shield: ^1.2.0
Then fetch dependencies:
flutter pub get
Platform Setup #
Android #
Ensure your android/app/build.gradle targets a compatible API level:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 21 // Android 5.0+
targetSdkVersion 34
}
}
iOS #
Set the minimum iOS deployment target in your ios/Podfile:
platform :ios, '12.0'
If your app uses sensor-related checks, add the required usage descriptions to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Required for sensor security checks</string>
<key>NSMicrophoneUsageDescription</key>
<string>Required for sensor security checks</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Required for sensor security checks</string>
Firebase App Check Setup #
Firebase App Check provides the strongest device attestation — it defeats Magisk + Shamiko by verifying integrity server-side via Google. No custom backend is required.
Step 1 — Create Firebase Project #
- Go to console.firebase.google.com
- Create a project → Add an Android app with your package name
- Download
google-services.json→ place it inandroid/app/ - For iOS: download
GoogleService-Info.plist→ place it inios/Runner/
Step 2 — Enable App Check #
Firebase Console → Build → App Check → Register your app:
- Android → Select Play Integrity
- iOS → Select App Attest (or DeviceCheck for older devices)
Step 3 — Add google-services plugin #
In android/build.gradle:
dependencies {
classpath 'com.google.gms:google-services:4.4.2'
}
In android/app/build.gradle:
apply plugin: 'com.google.gms.google-services'
Step 4 — Initialize in main.dart #
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_app_check/firebase_app_check.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FirebaseAppCheck.instance.activate(
androidProvider: AndroidProvider.playIntegrity, // production
// androidProvider: AndroidProvider.debug, // testing only
appleProvider: AppleProvider.appAttest, // iOS
);
runApp(const MyApp());
}
Note: Firebase App Check is optional. All other Flutter Shield checks work independently without Firebase.
Quick Start #
import 'package:flutter_shield/flutter_shield.dart';
void main() async {
final report = await FlutterShield.performFullSecurityCheck();
if (report.isSecure) {
print('✅ Device passed all ${report.totalChecks} security checks.');
} else {
print('⚠️ ${report.vulnerabilitiesFound} issue(s) found:');
for (final v in report.vulnerabilities) {
print(' • ${v.type.name}: ${v.message}');
}
}
}
Usage #
Full Security Scan #
Run all 31 checks concurrently in a single call:
Future<void> runFullScan() async {
final report = await FlutterShield.performFullSecurityCheck();
print('Scan completed at: ${report.timestamp}');
print('Total checks : ${report.totalChecks}');
print('Vulnerabilities: ${report.vulnerabilitiesFound}');
print('Is secure : ${report.isSecure}');
for (final result in report.results) {
final status = result.isVulnerable ? '❌ FAIL' : '✅ PASS';
print('$status ${result.type.name}: ${result.message}');
}
}
Individual Checks #
Run specific checks when you need targeted enforcement:
// Device integrity
final rootCheck = await FlutterShield.checkRootedJailbroken();
final debugCheck = await FlutterShield.checkDebuggable();
final usbCheck = await FlutterShield.checkUsbDebugging(); // Android
final emulatorCheck = await FlutterShield.checkEmulator();
final malwareCheck = await FlutterShield.checkMalware();
// Storage
final storageCheck = await FlutterShield.checkLocalStorage();
final plaintextCheck = await FlutterShield.checkPlaintextData();
final keystoreCheck = await FlutterShield.checkKeychainKeystore();
// Authentication
final biometricCheck = await FlutterShield.checkBiometricHandling();
final screenLockCheck = await FlutterShield.checkScreenLock();
// UI
final screenshotCheck = await FlutterShield.checkScreenshotRestriction();
final clipboardCheck = await FlutterShield.checkClipboard();
// WebView
final webViewDebugCheck = await FlutterShield.checkWebViewDebugging();
if (rootCheck.isVulnerable) {
print('🚨 Device is rooted/jailbroken: ${rootCheck.message}');
}
Firebase App Check #
The strongest check — verifies both app and device integrity via Google's servers. Defeats Magisk + Shamiko.
// Requires Firebase.initializeApp() + FirebaseAppCheck.activate() first
final appCheckResult = await FlutterShield.checkFirebaseAppCheck();
if (appCheckResult.isVulnerable) {
// Device or app failed attestation — block access
showSecurityBlockedScreen();
} else {
print('App Check passed: ${appCheckResult.message}');
}
Combined with root detection for maximum coverage:
Future<bool> isDeviceTrusted() async {
final results = await Future.wait([
FlutterShield.checkRootedJailbroken(),
FlutterShield.checkEmulator(),
FlutterShield.checkFirebaseAppCheck(),
]);
return results.every((r) => !r.isVulnerable);
}
Play Integrity Token (Manual Server Verification) #
If you want to verify the token on your own backend instead of using Firebase:
final result = await FlutterShield.checkPlayIntegrity();
if (!result.isVulnerable) {
final token = result.details?['token'] as String?;
final nonce = result.details?['nonce'] as String?;
// Send token to your server for verification
await yourBackend.verifyIntegrityToken(token!, nonce!);
}
Handling Results #
Use the structured SecurityCheckResult to drive UI or business logic:
Future<void> handleSecurityCheck(BuildContext context) async {
final result = await FlutterShield.checkRootedJailbroken();
switch (result.isVulnerable) {
case true:
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text('Security Warning'),
content: Text(result.message),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Understood'),
),
],
),
);
case false:
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('✅ Device integrity check passed')),
);
}
}
Conditional Feature Gating #
Block sensitive features on compromised devices:
Future<bool> canAccessSensitiveFeature() async {
// Run checks in parallel for speed
final results = await Future.wait([
FlutterShield.checkRootedJailbroken(),
FlutterShield.checkDebuggable(),
FlutterShield.checkEmulator(),
]);
final isCompromised = results.any((r) => r.isVulnerable);
return !isCompromised;
}
// Usage
Future<void> openPaymentScreen() async {
if (!await canAccessSensitiveFeature()) {
// Deny access on compromised devices
showSecurityWarning();
return;
}
Navigator.push(context, MaterialPageRoute(builder: (_) => const PaymentScreen()));
}
API Reference #
FlutterShield #
All methods are static and return Future<SecurityCheckResult> unless otherwise noted.
Device Integrity
| Method | Description | Platform |
|---|---|---|
checkRootedJailbroken() |
Detects rooted (Android) or jailbroken (iOS) device using multiple methods | Both |
checkDebuggable() |
Checks if the app was built with the debuggable flag | Both |
checkUsbDebugging() |
Checks if ADB / USB debugging is currently enabled | Android |
checkEmulator() |
Detects Android emulator or iOS Simulator | Both |
checkMalware() |
Basic suspicious-app detection | Android |
Storage Security
| Method | Description | Platform |
|---|---|---|
checkLocalStorage() |
Checks for unencrypted SharedPreferences / UserDefaults usage | Both |
checkPlaintextData() |
Detects plaintext files (.txt, .json, .xml) in app storage |
Both |
checkKeychainKeystore() |
Validates Keychain (iOS) / Keystore (Android) usage | Both |
checkFilePermissions() |
Checks for files with overly broad permissions | Both |
checkExternalStorage() |
Detects sensitive data written to external storage | Android |
checkBackupEnabled() |
Checks whether Android backup is enabled for app data | Android |
Authentication
| Method | Description | Platform |
|---|---|---|
checkBiometricHandling() |
Validates biometric authentication availability | Both |
checkBiometricBypass() |
Checks for biometric bypass vulnerabilities | Both |
checkScreenLock() |
Verifies that a screen lock / PIN is enforced | Both |
UI Security
| Method | Description | Platform |
|---|---|---|
checkScreenshotRestriction() |
Checks if FLAG_SECURE (Android) prevents screenshots |
Both |
checkScreenRecording() |
Detects active screen recording (iOS: UIScreen.isCaptured) |
Both |
checkClipboard() |
Checks clipboard monitoring for sensitive data | Both |
checkOverlayAttack() |
Detects tapjacking / overlay attack exposure | Android |
checkBackgroundDataExposure() |
Checks for data exposure when app goes to background | Both |
checkRecentApps() |
Checks if app switcher preview exposes sensitive screens | Both |
Communication
| Method | Description | Platform |
|---|---|---|
checkIPC() |
Validates inter-process communication security | Both |
checkIntentHijacking() |
Checks for exported intent vulnerabilities | Android |
checkBroadcastReceiver() |
Checks for exposed broadcast receivers | Android |
checkDeepLink() |
Validates deep link / URL scheme security | Both |
WebView
| Method | Description | Platform |
|---|---|---|
checkWebViewDebugging() |
Detects if WebView remote debugging is enabled | Both |
checkWebViewJavaScript() |
Checks WebView JavaScript interface security | Both |
Permissions & Runtime
| Method | Description | Platform |
|---|---|---|
checkRuntimePermissions() |
Validates runtime permission handling | Both |
checkAutofill() |
Checks autofill security for sensitive fields | Both |
checkSensorAbuse() |
Checks for unauthorized camera / microphone / GPS access | Both |
Other
| Method | Description | Platform |
|---|---|---|
checkDeviceTime() |
Checks if device uses automatic network time | Android |
checkSideChannel() |
Checks for side-channel attack exposure | Both |
App Attestation
| Method | Description | Platform |
|---|---|---|
checkPlayIntegrity() |
Requests a Play Integrity token. Returns token in details['token'] for server-side verification via Google Play Integrity API. Defeats Magisk/Shamiko when verified server-side. |
Android |
checkFirebaseAppCheck() |
Verifies device and app integrity via Firebase App Check (Play Integrity on Android, App Attest on iOS). No custom backend needed — Firebase handles verification. Requires Firebase.initializeApp() and FirebaseAppCheck.activate(). |
Both |
Comprehensive Check
// Returns Future<SecurityReport> — includes all 33 checks including Play Integrity
final report = await FlutterShield.performFullSecurityCheck();
Note:
checkFirebaseAppCheck()is NOT included inperformFullSecurityCheck()because it requires Firebase to be initialized first. Call it separately afterFirebaseAppCheck.activate().
SecurityCheckResult #
class SecurityCheckResult {
final VulnerabilityType type; // Which vulnerability was checked
final bool isVulnerable; // true = issue found
final String message; // Human-readable description
final Map<String, dynamic>? details; // Optional platform-specific metadata
}
SecurityReport #
class SecurityReport {
final List<SecurityCheckResult> results; // All 31 check results
final DateTime timestamp; // When the scan ran
final int totalChecks; // Always 31
final int vulnerabilitiesFound; // Number of failed checks
bool get isSecure; // true when vulnerabilitiesFound == 0
List<SecurityCheckResult> get vulnerabilities; // Only failed results
}
VulnerabilityType enum #
enum VulnerabilityType {
// Device Integrity
rootedJailbroken, debuggableApp, usbDebugging, emulatorDetection, malwareExposure,
// Storage Security
insecureLocalStorage, plaintextData, improperKeychainKeystore,
insecureFilePermissions, externalStorageSensitiveData, backupEnabled,
// Authentication
weakBiometricHandling, biometricBypass, screenLockNotEnforced,
// UI Security
screenshotNotRestricted, screenRecordingNotRestricted, clipboardLeakage,
overlayAttack, backgroundDataExposure, recentAppsExposure,
// Communication
insecureIPC, intentHijacking, broadcastReceiverExposure, deepLinkHijacking,
// WebView
webViewDebugging, webViewJavaScriptAbuse,
// Permissions & Runtime
runtimePermissionMissing, insecureAutofill, sensorAbuse,
// Other
trustingDeviceTime, sideChannelAttacks,
// App Attestation
playIntegrityFailed, // Play Integrity token request failed
firebaseAppCheckFailed, // Firebase App Check attestation failed
unknown,
}
Security Categories #
Flutter Shield — 33 Checks
│
├── 🔒 Device Integrity (5)
│ ├── Root / Jailbreak detection [7 vectors: su paths, test-keys,
│ │ Magisk paths, root packages,
│ │ dangerous props, writable /system]
│ ├── Debuggable app flag + debug signing cert
│ ├── USB debugging status [Android]
│ ├── Emulator / Simulator
│ └── Malware / suspicious apps [Android]
│
├── 🗄️ Storage Security (6)
│ ├── Unencrypted SharedPreferences / UserDefaults
│ ├── Plaintext files in app storage
│ ├── Keychain / Keystore validation
│ ├── File permissions (rwx)
│ ├── External storage usage [Android]
│ └── Backup configuration [Android]
│
├── 🔑 Authentication (3)
│ ├── Biometric handling
│ ├── Biometric bypass
│ └── Screen lock / PIN enforcement
│
├── 🖥️ UI Security (6)
│ ├── Screenshot restriction (FLAG_SECURE)
│ ├── Screen recording detection
│ ├── Clipboard monitoring
│ ├── Overlay / tapjacking
│ ├── Background data exposure
│ └── Recent apps preview
│
├── 📡 Communication (4)
│ ├── IPC security
│ ├── Intent hijacking [Android]
│ ├── Broadcast receiver exposure [Android]
│ └── Deep link hijacking
│
├── 🌐 WebView (2)
│ ├── WebView remote debugging
│ └── JavaScript interface security
│
├── ⚙️ Permissions & Runtime (3)
│ ├── Runtime permission validation
│ ├── Autofill security
│ └── Sensor abuse (Camera/Mic/GPS)
│
├── 🔬 Other (2)
│ ├── Device time trust (Auto time) [Android]
│ └── Side-channel attack exposure
│
└── 🛡️ App Attestation (2)
├── Play Integrity API token [Android — verify server-side]
└── Firebase App Check [Android + iOS — no server needed]
Best Practices #
1. Check at startup
@override
void initState() {
super.initState();
_runSecurityCheck();
}
2. Gate sensitive features
// Never allow payments or biometric auth on rooted devices
final rootCheck = await FlutterShield.checkRootedJailbroken();
if (rootCheck.isVulnerable) blockSensitiveFeature();
3. Run checks in parallel when you need multiple results
final results = await Future.wait([
FlutterShield.checkRootedJailbroken(),
FlutterShield.checkDebuggable(),
FlutterShield.checkEmulator(),
]);
4. Log security events
final report = await FlutterShield.performFullSecurityCheck();
if (!report.isSecure) {
analytics.logEvent('security_issues_found', {
'count': report.vulnerabilitiesFound,
'issues': report.vulnerabilities.map((v) => v.type.name).toList(),
});
}
5. Educate users gracefully
Rather than silently blocking, show clear explanations so users understand the risk and can take action (e.g., disable USB debugging).
Platform Differences #
| Check | Android | iOS |
|---|---|---|
| Root / Jailbreak | ✅ su binaries, Magisk paths, root packages, build tags | ✅ Cydia paths, DYLD |
| USB Debugging | ✅ ADB setting | ➖ N/A |
| External Storage | ✅ | ➖ Sandboxed |
| Intent Hijacking | ✅ | ➖ N/A |
| Broadcast Receivers | ✅ | ➖ N/A |
| Backup Enabled | ✅ | ➖ Different model |
| Screen Recording | ✅ Guided | ✅ UIScreen.isCaptured |
| Device Time | ✅ Auto-time setting | ➖ Server-side only |
| Overlay Attack | ✅ | ✅ System-protected |
| Play Integrity | ✅ Google Play Services | ➖ N/A |
| Firebase App Check | ✅ Play Integrity provider | ✅ App Attest / DeviceCheck |
Limitations #
Some checks provide guidance rather than automated enforcement because they require app-specific knowledge:
- Keychain / Keystore — validation requires your encryption implementation
- WebView — JavaScript security requires runtime WebView inspection
- Autofill — requires field-level
autofillHintsconfiguration - Biometric bypass — requires app-specific authentication flow analysis
- Malware detection — basic package-name matching; not a full antivirus scan
These checks still return structured results so you can integrate them into your own logic.
Contributing #
Contributions, issues, and feature requests are welcome!
- Fork the repository
- Create your feature branch:
git checkout -b feature/my-feature - Commit your changes:
git commit -m 'feat: add my feature' - Push to the branch:
git push origin feature/my-feature - Open a Pull Request
Please follow the existing code style and add tests for new functionality.
Security Disclosure #
Found a security vulnerability in Flutter Shield itself?
Please email sanjaysharmajw@gmail.com — do not open a public issue.
License #
This project is licensed under the MIT License — see the LICENSE file for details.
Disclaimer #
Flutter Shield provides detection and reporting mechanisms. It should be one layer of a defence-in-depth security strategy — not your only safeguard. Always follow secure coding practices, apply certificate pinning, encrypt sensitive data at rest, and validate inputs at every system boundary.


