Kryvon
A structured mobile security baseline framework for Flutter applications.
Kryvon provides a guard-based runtime security layer that runs checks in parallel, aggregates risk across multiple threat signals, and enforces policy through a configurable enforcement strategy — all with a minimal API surface.
Platform support: Android only. iOS support is not currently implemented.
Features
- Root detection — 6 native indicators (su binary, su execution, dangerous props, writable system, known root apps, test keys)
- Debugger detection — 5 native signals (tracerPid, JDWP, Android debugger, system-debuggable flag, debuggable app flag)
- Parallel guard execution — all guards run concurrently via
Future.wait - Risk aggregation — severity scores combined with a threat-diversity bonus
- Configurable policy — set your own block threshold, enforcement strategy, and threat callback
- Extensible — implement
Guardto add custom detectors
Installation
Add to your pubspec.yaml:
dependencies:
kryvon: ^0.1.0
Then run:
flutter pub get
Quick start
import 'package:kryvon/kryvon.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
Kryvon.initialize(
policy: KryvonPolicy(
blockThreshold: ThreatSeverity.high,
enforcementStrategy: EnforcementStrategy.emitOnly,
onThreat: (event) {
print('Threat: ${event.type.name} [${event.severity.name}]');
},
),
);
await Kryvon.runChecks();
runApp(const MyApp());
}
For high-security applications, use the pre-configured fintech policy:
Kryvon.initialize(policy: KryvonPolicy.fintech());
await Kryvon.runChecks();
KryvonPolicy.fintech() blocks at ThreatSeverity.medium and terminates the app when exceeded.
API reference
Kryvon
The static entry point. All interaction goes through this class.
| Method | Description |
|---|---|
Kryvon.initialize({required policy, logLevel}) |
Configure and start Kryvon. Auto-registers RootGuard and DebuggerGuard. |
Kryvon.registerGuard(guard) |
Add a custom Guard to the pipeline. Call after initialize. |
Kryvon.runChecks() |
Run all guards in parallel, aggregate risk, and enforce policy. |
KryvonPolicy
Controls detection thresholds and enforcement behaviour.
KryvonPolicy({
ThreatSeverity blockThreshold, // default: ThreatSeverity.high
EnforcementStrategy enforcementStrategy, // default: EnforcementStrategy.emitOnly
ThreatHandler? onThreat, // callback per individual ThreatEvent
})
| Factory | Description |
|---|---|
KryvonPolicy.fintech() |
blockThreshold: medium, enforcementStrategy: terminateApp |
ThreatSeverity
| Value | Description |
|---|---|
low |
Informational; no immediate risk |
medium |
Moderate risk; worth monitoring |
high |
Significant risk; consider blocking |
critical |
Severe risk; enforce immediately |
ThreatType
| Value | Description |
|---|---|
rootDetected |
Device root indicators found |
debuggerDetected |
Debugger or debug signal active |
emulatorDetected |
App running in an emulator (not yet implemented) |
insecureStorage |
Sensitive data in insecure location (not yet implemented) |
networkPinningFailure |
Certificate/key pinning failed (not yet implemented) |
deviceCompromised |
Synthetic aggregate event emitted after all guards complete |
EnforcementStrategy
| Value | Description |
|---|---|
emitOnly |
Log and call onThreat; no further action |
terminateApp |
Call exit(1) after logging |
LogLevel
Pass to Kryvon.initialize via the logLevel parameter.
| Value | Description |
|---|---|
debug |
Verbose — guard lifecycle events |
info |
General operational messages (default) |
warning |
Non-fatal issues |
error |
Guard or runtime failures |
silent |
No output |
Root detection
RootGuard delegates to the native RootDetector.kt over the com.kryvon.runtime method channel. Six indicators are checked and mapped to severity:
| Indicator | Severity |
|---|---|
suExecution |
critical |
suBinary |
high |
dangerousProps |
high |
writableSystem |
high |
knownRootApp |
medium |
testKeys |
medium |
The highest-priority indicator determines the event severity.
Debugger detection
DebuggerGuard delegates to the native DebuggerDetector.kt. Five signals are checked and mapped to severity:
| Signal | Severity |
|---|---|
tracerPid |
critical |
androidDebugger |
high |
systemDebuggable |
high |
jdwpEnabled |
medium |
debuggableApp |
medium |
Risk aggregation
After all guards run, RuntimeRiskAggregator combines their events into a single ThreatType.deviceCompromised event:
- Each event is scored:
low=1,medium=3,high=6,critical=10 - A diversity bonus of +2 is added per unique
ThreatTypepresent - The total maps to a final
ThreatSeverity:
| Total score | Severity |
|---|---|
| < 3 | low |
| 3–5 | medium |
| 6–9 | high |
| ≥ 10 | critical |
KryvonPolicy.shouldBlock is evaluated against this aggregated event. Individual events still fire onThreat as they are produced.
Custom guards
Implement the Guard interface to add your own detectors:
class EmulatorGuard implements Guard {
@override
Future<List<ThreatEvent>> check() async {
final isEmulator = await _detectEmulator();
if (!isEmulator) return [];
return [
ThreatEvent(
type: ThreatType.emulatorDetected,
severity: ThreatSeverity.high,
),
];
}
}
// Register after initialize:
Kryvon.registerGuard(EmulatorGuard());
Guards must not throw — any unhandled exception is caught by the runtime and treated as an empty result so that other guards are not blocked.
Architecture overview
Kryvon.runChecks()
│
├── RootGuard.check() ──► RootDetector ──► KotlinRootDetector.kt
├── DebuggerGuard.check() ──► DebuggerDetector ──► KotlinDebuggerDetector.kt
└── [custom guards] ...
│
▼ (Future.wait — parallel)
List<ThreatEvent>
│
├── onThreat(event) × N (per individual event)
│
▼
RuntimeRiskAggregator.aggregate()
│
▼
ThreatEvent(type: deviceCompromised, severity: aggregated)
│
KryvonPolicy.shouldBlock?
│
▼
EnforcementExecutor.execute(strategy, event)
Requirements
- Flutter
>=3.3.0 - Dart SDK
^3.9.2 - Android only