Skip to content

Commit

Permalink
chore(release): freeRASP 1.6.0 (#19)
Browse files Browse the repository at this point in the history
* feat(Android): add malware detection

* feat(ts): add malware detection

* chore(ts): generate dist files

* feat(example): add malware detection

* chore(release): freeRASP 1.6.0

* docs: update changelog

* chore(ts): refactoring

* chore(example): update add to whitelist

* chore(Android): rename malware to malwareConfig

* chore(Android): make applicationinfo nullable

* chore(Android): add exception logs, improve json parsing

* ci: add ci

* chore: add package lock

* chore: add build

* feat: update SDKs for Android to 12.0.0 and iOS to 6.6.3

* feat(example): bump gradle wrapper in example app

* docs: updadete readme
  • Loading branch information
tompsota authored Nov 15, 2024
1 parent 17d55f3 commit 0cbe5be
Show file tree
Hide file tree
Showing 71 changed files with 19,928 additions and 713 deletions.
10 changes: 0 additions & 10 deletions .eslintrc

This file was deleted.

17 changes: 17 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Setup
description: Setup Node.js and install dependencies

runs:
using: composite
steps:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version-file: .nvmrc

- name: Install dependencies
run: |
npm ci
npm ci --prefix example
shell: bash
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: CI
on:
push:
branches:
- main
paths-ignore:
- '**/*.md'
- '.github/**'
pull_request:
branches:
- main
paths-ignore:
- '**/*.md'
- '.github/**'

jobs:
static-analysis:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup
uses: ./.github/actions/setup

- name: Lint files
run: npm run eslint -- --max-warnings=0

- name: Typecheck files
run: npm run typecheck

- name: Format check
run: npm run prettier -- --check

build:
timeout-minutes: 30
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup
uses: ./.github/actions/setup

- name: Build package
run: npm run ionic:build
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,43 @@ 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).

## [1.6.0] - 2024-11-15

- Android SDK version: 12.0.0
- iOS SDK version: 6.6.3

### Capacitor

#### Added

- Added configuration fields for malware detection

#### Fixed

- Resolved compatibilty issues with JDK 21 [(issue #21)](https://github.com/talsec/Free-RASP-Capacitor/issues/21)

### Android

#### Added

- New feature: **malware detection** as a new callback for enhanced app security

#### Fixed

- Refactoring Magisk checks in the root detection

### iOS

#### Added

- Enhanced security with **[Serotonin Jailbreak](https://github.com/SerotoninApp/Serotonin) Detection** to identify compromised devices.

#### Changed

- Updated SDK code signing; it will now be signed with:
- Team ID: PBDDS45LQS
- Team Name: Lynx SFT s.r.o.

## [1.5.3] - 2024-10-28
- Android SDK version: 11.1.3
- iOS SDK version: 6.6.1
Expand Down
9 changes: 8 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:8.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:1.9.25"
}
}

apply plugin: 'com.android.library'
apply plugin: 'org.jetbrains.kotlin.android'
apply plugin: 'kotlinx-serialization'

android {
namespace "com.aheaditec.freerasp"
Expand All @@ -48,6 +50,10 @@ android {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
jvmTarget = "17"
}
}

repositories {
Expand All @@ -67,9 +73,10 @@ dependencies {
implementation project(':capacitor-android')
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
implementation "androidx.core:core-ktx:$androidCoreKtxVersion"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"

implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:11.1.3'
implementation 'com.aheaditec.talsec.security:TalsecSecurity-Community-Capacitor:12.0.0'
}
40 changes: 38 additions & 2 deletions android/src/main/java/com/aheaditec/freerasp/FreeraspPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.aheaditec.freerasp

import com.aheaditec.freerasp.utils.getArraySafe
import com.aheaditec.freerasp.utils.getNestedArraySafe
import com.aheaditec.freerasp.utils.toEncodedJSArray
import com.aheaditec.talsec_security.security.api.SuspiciousAppInfo
import com.aheaditec.talsec_security.security.api.Talsec
import com.aheaditec.talsec_security.security.api.TalsecConfig
import com.aheaditec.talsec_security.security.api.ThreatListener
Expand Down Expand Up @@ -31,7 +35,6 @@ class FreeraspPlugin : Plugin() {
bridge.activity.runOnUiThread {
Talsec.start(context, talsecConfig)
}
Talsec.start(context, talsecConfig)
call.resolve(JSObject().put("started", true))
} catch (e: Exception) {
call.reject("Error during Talsec Native plugin initialization - ${e.message}", "TalsecInitializationError", e)
Expand Down Expand Up @@ -70,7 +73,7 @@ class FreeraspPlugin : Plugin() {
fun getThreatChannelData(call: PluginCall) {
val channelData = JSONArray(
(listOf(
THREAT_CHANNEL_NAME, THREAT_CHANNEL_KEY
THREAT_CHANNEL_NAME, THREAT_CHANNEL_KEY, MALWARE_CHANNEL_KEY
))
)
call.resolve(JSObject().put("ids", channelData))
Expand All @@ -85,10 +88,34 @@ class FreeraspPlugin : Plugin() {
android.os.Process.killProcess(android.os.Process.myPid())
}

/**
* Add app with given package name to Talsec Malware Whitelist
* @param packageName - package name of the whitelisted app
* @return true if successful
*/
@PluginMethod
fun addToWhitelist(call: PluginCall) {
val packageName = call.getString("packageName")
if (packageName.isNullOrEmpty()) {
call.reject(
"Package name argument is missing or empty in the call",
"MissingArgumentError"
)
return
}
Talsec.addToWhitelist(context, packageName)
call.resolve(JSObject().put("result", true))
}

internal fun notifyListeners(threat: Threat) {
notifyListeners(THREAT_CHANNEL_NAME, JSObject().put(THREAT_CHANNEL_KEY, threat.value), true)
}

internal fun notifyMalware(suspiciousApps: MutableList<SuspiciousAppInfo>) {
notifyListeners(THREAT_CHANNEL_NAME, JSObject().put(THREAT_CHANNEL_KEY, Threat.Malware.value).put(
MALWARE_CHANNEL_KEY, suspiciousApps.toEncodedJSArray(context)), true)
}

private fun buildTalsecConfigThrowing(configJson: JSObject): TalsecConfig {
val androidConfig = configJson.getJSONObject("androidConfig")
val packageName = androidConfig.getString("packageName")
Expand All @@ -98,6 +125,13 @@ class FreeraspPlugin : Plugin() {
.supportedAlternativeStores(androidConfig.getArraySafe("supportedAlternativeStores"))
.prod(configJson.getBool("isProd") ?: true)

if (androidConfig.has("malwareConfig")) {
val malwareConfig = androidConfig.getJSONObject("malwareConfig")
talsecBuilder.whitelistedInstallationSources(malwareConfig.getArraySafe("whitelistedInstallationSources"))
talsecBuilder.blacklistedHashes(malwareConfig.getArraySafe("blacklistedHashes"))
talsecBuilder.blacklistedPackageNames(malwareConfig.getArraySafe("blacklistedPackageNames"))
talsecBuilder.suspiciousPermissions(malwareConfig.getNestedArraySafe("suspiciousPermissions"))
}
return talsecBuilder.build()
}

Expand All @@ -106,5 +140,7 @@ class FreeraspPlugin : Plugin() {
.toString() // name of the channel over which threat callbacks are sent
private val THREAT_CHANNEL_KEY = (10000..999999999).random()
.toString() // key of the argument map under which threats are expected
val MALWARE_CHANNEL_KEY = (10000..999999999).random()
.toString() // key of the argument map under which malware data is expected
}
}
4 changes: 3 additions & 1 deletion android/src/main/java/com/aheaditec/freerasp/Threat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal sealed class Threat(val value: Int) {
object ObfuscationIssues : Threat((10000..999999999).random())
object SystemVPN : Threat((10000..999999999).random())
object DevMode : Threat((10000..999999999).random())
object Malware : Threat((10000..999999999).random())

companion object {
internal fun getThreatValues(): JSONArray {
Expand All @@ -40,7 +41,8 @@ internal sealed class Threat(val value: Int) {
UnofficialStore.value,
Overlay.value,
ObfuscationIssues.value,
DevMode.value
DevMode.value,
Malware.value
))
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ internal class TalsecThreatHandler(private val instance: FreeraspPlugin) :
instance.notifyListeners(Threat.ObfuscationIssues)
}

override fun onMalwareDetected(p0: MutableList<SuspiciousAppInfo>?) {}
override fun onMalwareDetected(suspiciousAppInfos: MutableList<SuspiciousAppInfo>?) {
instance.notifyMalware(suspiciousAppInfos ?: mutableListOf())
}

override fun onUnlockedDeviceDetected() {
instance.notifyListeners(Threat.Passcode)
Expand Down
22 changes: 0 additions & 22 deletions android/src/main/java/com/aheaditec/freerasp/Utils.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.aheaditec.freerasp.models

import kotlinx.serialization.Serializable


/**
* Simplified, serializable wrapper for Talsec's SuspiciousAppInfo
*/
@Serializable
data class CapSuspiciousAppInfo(
val packageInfo: CapPackageInfo,
val reason: String,
)

/**
* Simplified, serializable wrapper for Android's PackageInfo
*/
@Serializable
data class CapPackageInfo(
val packageName: String,
val appName: String?,
val version: String?,
val appIcon: String?,
val installerStore: String?
)
Loading

0 comments on commit 0cbe5be

Please sign in to comment.