safety_net_flutter 1.0.0 copy "safety_net_flutter: ^1.0.0" to clipboard
safety_net_flutter: ^1.0.0 copied to clipboard

Flutter plugin wrapping SafetyNet (iOS) and SafetyNetAndroid for report-only root/jailbreak/tamper/debugger detection on both platforms.

safety_net_flutter #

A Flutter plugin wrapping SafetyNet (iOS) and SafetyNetAndroid (Android) behind one Dart API: root/jailbreak/tamper/debugger detection for Flutter apps.

Like both native libraries it wraps, this plugin never auto-reacts. It only reports what it finds — your app decides what to do with the result (block a screen, log it, step up authentication, etc.).

What each platform actually runs #

Platform Underlying check
iOS SafetyNet.shared.check() — the full scored pipeline: jailbreak signals, debugger/tracing, code-signature integrity, proxy/VPN. See the SafetyNet README for the full signal list and scoring thresholds.
Android SafetyNetAndroid.checkRoot() + SafetyNetAndroid.checkDebugger(), combined into one result. See the SafetyNetAndroid README for the full check list.

The Dart-facing result is intentionally a minimal, unified shape rather than exposing each platform's full native richness (e.g. iOS's numeric ThreatLevel isn't surfaced) — apps that need finer-grained platform-specific data should call the native SDKs directly on that platform.

class SafetyNetCheckResult {
  final bool isCompromised;
  final List<String> reasons; // raw check names that fired, e.g. "jailbreakDetected"
}

Installation #

Add the dependency to your app's pubspec.yaml:

dependencies:
  safety_net_flutter:
    git:
      url: https://github.com/DipakPanchasara/SafetyNetFlutter.git
      tag: 1.0.0 # once tagged; otherwise omit to track the default branch

Then:

flutter pub get

iOS dependency resolution #

SafetyNet is not yet published to CocoaPods trunk, so the two supported iOS integration paths differ slightly:

  • If your app uses Swift Package Manager for iOS plugins (Flutter's modern default, ios/Flutter/Generated.xcconfig referencing Package.swift): nothing further to do. This plugin's own Package.swift already declares the SafetyNet git dependency (https://github.com/DipakPanchasara/SafetyNet.git, from 2.1.0), and SPM resolves it transitively.

  • If your app uses CocoaPods for iOS plugins (ios/Podfile): you must add these two lines to your own Podfile so CocoaPods can resolve SafetyNet and its own SafetyNetObjC dependency (a podspec's s.dependency can only point at a name registered in a spec repo, not an arbitrary git URL — only a Podfile's pod line can do that):

    pod 'SafetyNet', :git => 'https://github.com/DipakPanchasara/SafetyNet.git', :tag => '2.1.0'
    pod 'SafetyNetObjC', :git => 'https://github.com/DipakPanchasara/SafetyNet.git', :tag => '2.1.0'
    

    Then run pod install from ios/. (See example/ios/Podfile in this repo for a working reference.)

No other iOS setup is required — see "Do I need to touch AppDelegate?" below.

Android dependency resolution #

The Android side depends on SafetyNetAndroid via Maven Central (io.github.dipakpanchasara:safetynet-android). As long as your app's repository list includes mavenCentral() — true by default in virtually every Flutter/Gradle project — no further setup is required.

Usage #

import 'package:safety_net_flutter/safety_net_flutter.dart';

Future<void> checkDeviceSecurity() async {
  final result = await SafetyNetFlutter.check();

  if (result.isCompromised) {
    // Your call: log it, show a warning, require step-up auth, etc.
    // SafetyNetFlutter itself never blocks UI or logs the user out.
    print('Device flagged: ${result.reasons}');
  }
}

A common pattern is running the check once at app launch, before runApp():

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final result = await SafetyNetFlutter.check();
  if (result.isCompromised) {
    // record/report as appropriate for your app
  }

  runApp(const MyApp());
}

Do I need to touch AppDelegate? #

No manual AppDelegate edit is needed to register this plugin. Flutter's GeneratedPluginRegistrant (generated automatically at build time) registers every plugin listed in your pubspec.yaml, including this one — that's true whether your AppDelegate is Swift or Objective-C, and regardless of whether you use SPM or CocoaPods for the iOS side.

Two things worth knowing that are independent of Flutter's plugin registration:

  • SafetyNet's anti-ptrace protection (AntiDebugBridge.m's constructor) runs automatically the moment the SafetyNet dynamic library is loaded into the process — this happens at process launch, before Dart or Flutter even start, and needs no wiring on your part.
  • If you specifically want the check result available as early as possible in the app lifecycle (e.g. before the first frame renders), call SafetyNetFlutter.check() at the top of Dart's main() as shown above — there's no AppDelegate-level equivalent needed for this, since the check itself is a Dart-initiated platform channel call.

Example app #

See example/ for a minimal app that runs the check on launch and displays isCompromised and reasons.

cd example
flutter run

Repository layout #

  • lib/ — Dart-facing API (SafetyNetFlutter.check(), SafetyNetCheckResult, platform interface, method channel implementation).
  • ios/ — iOS plugin implementation (Swift), wrapping SafetyNet.
  • android/ — Android plugin implementation (Kotlin), wrapping SafetyNetAndroid.
  • example/ — demo app exercising the plugin on both platforms.
0
likes
160
points
--
downloads

Documentation

API reference

Publisher

unverified uploader

Flutter plugin wrapping SafetyNet (iOS) and SafetyNetAndroid for report-only root/jailbreak/tamper/debugger detection on both platforms.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on safety_net_flutter

Packages that implement safety_net_flutter