Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: freeRASP 6.10.0 #153

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [6.10.0] - 2024-12-17

- iOS SDK version: 6.6.3
- Android SDK version: 13.0.0

### Flutter

#### Changed

- App icons for detected malware are not fetched automatically anymore, which reduces computation required to retrieve malware data. From now on, app icons have to be retrieved using the `getAppIcon` method

### Android

#### Changed

- Malware data is now parsed on background thread to improve responsiveness

## [6.9.0] - 2024-11-19
- Android SDK version: 13.0.0
- iOS SDK version: 6.6.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ private fun PackageInfo.toPigeon(context: Context): FlutterPackageInfo {
context.packageManager.getApplicationLabel(it) as String
},
version = getVersionString(),
appIcon = Utils.parseIconBase64(context, packageName),
installationSource = Utils.getInstallerPackageName(context, packageName),
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package com.aheaditec.freerasp.handlers

import android.content.Context
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.aheaditec.freerasp.runResultCatching
import com.aheaditec.freerasp.Utils
import com.aheaditec.freerasp.generated.TalsecPigeonApi
Expand All @@ -16,10 +22,13 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler
/**
* A method handler that creates and manages an [MethodChannel] for freeRASP methods.
*/
internal class MethodCallHandler : MethodCallHandler {
internal class MethodCallHandler : MethodCallHandler, LifecycleEventObserver {
private var context: Context? = null
private var methodChannel: MethodChannel? = null
private var pigeonApi: TalsecPigeonApi? = null
private val backgroundHandlerThread = HandlerThread("BackgroundThread").apply { start() }
private val backgroundHandler = Handler(backgroundHandlerThread.looper)
private val mainHandler = Handler(Looper.getMainLooper())

companion object {
private const val CHANNEL_NAME: String = "talsec.app/freerasp/methods"
Expand Down Expand Up @@ -82,6 +91,20 @@ internal class MethodCallHandler : MethodCallHandler {
TalsecThreatHandler.detachMethodSink()
}

override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
when (event) {
Lifecycle.Event.ON_DESTROY -> {
context?.let {
backgroundHandlerThread.quitSafely()
}
}

else -> {
// Nothing to do
}
}
}

/**
* Handles method calls received through the [MethodChannel].
*
Expand All @@ -92,6 +115,7 @@ internal class MethodCallHandler : MethodCallHandler {
when (call.method) {
"start" -> start(call, result)
"addToWhitelist" -> addToWhitelist(call, result)
"getAppIcon" -> getAppIcon(call, result)
else -> result.notImplemented()
}
}
Expand Down Expand Up @@ -124,4 +148,25 @@ internal class MethodCallHandler : MethodCallHandler {
result.success(null)
}
}

/**
* Retrieves app icon for the given package name.
*
* @param call The method call containing the package name.
* @param result The result handler of the method call.
*/
private fun getAppIcon(call: MethodCall, result: MethodChannel.Result) {
runResultCatching(result) {
val packageName = call.argument<String>("packageName")
?: throw NullPointerException("Package name cannot be null.")

backgroundHandler.post {
context?.let {
val appIcon = Utils.parseIconBase64(it, packageName)
mainHandler.post { result.success(appIcon) }
}
}

}
}
}
25 changes: 19 additions & 6 deletions example/lib/widgets/malware_bottom_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,25 @@ class MalwareListTile extends StatelessWidget {

@override
Widget build(BuildContext context) {
return ListTile(
title: Text(malware.packageInfo.packageName),
subtitle: Text('Reason: ${malware.reason}'),
leading: malware.packageInfo.appIcon == null
? const Icon(Icons.warning, color: Colors.red)
: Image.memory(base64.decode(malware.packageInfo.appIcon!)),
return FutureBuilder<String?>(
future: Talsec.instance.getAppIcon(malware.packageInfo.packageName),
builder: (context, snapshot) {
Widget appIcon;
if (snapshot.data != null) {
appIcon = Image.memory(base64.decode(snapshot.data!));
} else {
appIcon = const Icon(
Icons.error,
color: Colors.red,
);
}

return ListTile(
title: Text(malware.packageInfo.packageName),
subtitle: Text('Reason: ${malware.reason}'),
leading: appIcon,
);
},
);
}
}
12 changes: 12 additions & 0 deletions lib/src/errors/malware_failure_exception.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'package:freerasp/freerasp.dart';

/// An exception that is thrown when there is a failure in malware data parsing.
///
/// This exception extends the [TalsecException] class and includes an error
/// code of 'malware-failure'. It can include an optional [message] and
/// [stackTrace] parameter.
class MalwareFailureException extends TalsecException {
/// Constructs an instance of [MalwareFailureException].
const MalwareFailureException({super.message, super.stackTrace})
: super(code: 'malware-failure');
}
30 changes: 30 additions & 0 deletions lib/src/talsec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:freerasp/freerasp.dart';
import 'package:freerasp/src/errors/malware_failure_exception.dart';
import 'package:freerasp/src/generated/talsec_pigeon_api.g.dart';

/// A class which maintains all security related operations.
Expand Down Expand Up @@ -215,4 +216,33 @@ class Talsec {
// ignore: only_throw_errors
throw error;
}

/// Retrieves the app icon for the given [packageName] as base64 string.
///
/// Throws a [TalsecException] with error message description if
/// the app with given package name couldn't be obtained.
Future<String> getAppIcon(String packageName) async {
if (!Platform.isAndroid) {
throw UnimplementedError(
'Platform is not supported: $defaultTargetPlatform}',
);
}

try {
return await _getAppIcon(packageName);
} on PlatformException catch (e) {
throw TalsecException.fromPlatformException(e);
}
}

Future<String> _getAppIcon(String packageName) async {
final args = {'packageName': packageName};
final result = await methodChannel.invokeMethod<String>('getAppIcon', args);

if (result is! String) {
throw const MalwareFailureException(message: 'Malware App icon is null.');
}

return result;
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: freerasp
description: Flutter library for improving app security and threat monitoring on Android and iOS mobile devices. Learn more about provided features on the freeRASP's homepage first.
version: 6.9.0
version: 6.10.0
homepage: https://www.talsec.app/freerasp-in-app-protection-security-talsec
repository: https://github.com/talsec/Free-RASP-Flutter

Expand Down
Loading