Skip to content

feat: In-app malware scanning#250

Open
omeritzics wants to merge 34 commits intomainfrom
yara-scan
Open

feat: In-app malware scanning#250
omeritzics wants to merge 34 commits intomainfrom
yara-scan

Conversation

@omeritzics
Copy link
Owner

@omeritzics omeritzics commented Mar 11, 2026

Summary by CodeRabbit

  • New Features

    • YARA-based malware scanner with configurable auto-scan, auto-update, threat filtering and quarantine
    • Security settings UI and an About dialog showing app version
  • UI/UX

    • Updated input/dropdown styling: improved borders, spacing, and label hierarchy
  • Localization

    • Added English, German and French translations for all new security features
  • Removed Features

    • Deep linking
    • File export capability

omeritzics and others added 30 commits February 22, 2026 02:27
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Fix icon caching

* Fix

* style: auto-fix linting and formatting issues

* Quality

* style: auto-fix linting and formatting issues

* Optimize speed

* style: auto-fix linting and formatting issues

* Revert "style: auto-fix linting and formatting issues"

This reverts commit ab9727a.

* Revert "Optimize speed"

This reverts commit ea53327.

* Update nightly.yml

* Update README.md

* style: auto-fix linting and formatting issues

* Unify Flutter icon cache

* style: auto-fix linting and formatting issues

* Fix icon cache

* Migrate to built-in Flutter's design components

* Update Flutter

* style: auto-fix linting and formatting issues

* Fix builds

* Fixed icons

* style: auto-fix linting and formatting issues

* Fix build?

* Change app ID to io.github.omeritzics.updatium

* style: auto-fix linting and formatting issues

* Update README.md

* Update README.md

* Update README.md

* Attempt to fix Material You colors breaking design

* Move filter icon to the top

* style: auto-fix linting and formatting issues

* Move the grid view button to the top

* UI improvments

* style: auto-fix linting and formatting issues

* Update readme

* Update readme

* Update readme

* Fix build

* style: auto-fix linting and formatting issues

* Fix overflow

* style: auto-fix linting and formatting issues

* Fix signing problem(?)

* Fix build?

* Fix

* Release build fix

* Update Nightly builds

* Update Nightly builds

* Revert "Release build fix"

This reverts commit 257307d.

* Revert "Update Nightly builds"

This reverts commit 91b8f47.

* Fix release build?

* Update release.yml

* Update release.yml

* Update README.md

* Update release.yml

* UI fix

* Update Hebrew

* Bump SDK version

* Update Hebrew

* Fix Waydroid

* style: auto-fix linting and formatting issues

* style: auto-fix linting and formatting issues

* Revert "Fix Waydroid"

This reverts commit d879ba1.

* Add nightly-signed.yml

* Update nightly-signed.yml

* Update workflows

* Fix

* Should fix signed builds

* style: auto-fix linting and formatting issues

* Update pubspec.lock

* Replace flutter_keyboard_visibility

* style: auto-fix linting and formatting issues

* Replace shared_storage with docman

* style: auto-fix linting and formatting issues

* Fix typos

* style: auto-fix linting and formatting issues

* Another fix

* style: auto-fix linting and formatting issues

* Update dependencies

* Fix

* Delete .github/workflows/qama-unsigned.yml

* Fix?

* style: auto-fix linting and formatting issues

* Fix errors?

* Now it should fix the signing

* Another fix

* Another fix attempt

* Fix nightly.yml

* Try to add a different icon for the Nighly builds. #165

* Nightly new branding

* Sign Nightly builds by default

* Prepare for the new release

* A message about unofficial sources

* Fix the nightly build

* Some bug fixes

* style: auto-fix linting and formatting issues

* Revert "Fix the nightly build"

This reverts commit 9a1d9cd.

* Revert "Fix nightly.yml"

This reverts commit 0a68335.

* Revert "Nightly new branding"

This reverts commit 3e141c6.

* Revert "Try to add a different icon for the Nighly builds. #165"

This reverts commit 02dd713.

* Some more fixes

* Improve pure black theme

* Attempt to fix grid view bug

* Material You bug fix

* style: auto-fix linting and formatting issues

* Update badge style for GitHub release link

* Bug fixes

* style: auto-fix linting and formatting issues

* Selection fix

* UX/UI fixes

* style: auto-fix linting and formatting issues

* Update supported app sources in README

* Fix build

* style: auto-fix linting and formatting issues

* Selection fix #2

* style: auto-fix linting and formatting issues

* Fix spacing

* Revert "Fix spacing"

This reverts commit 1289296.

* Add consistent spacing constants to app pages

* style: auto-fix linting and formatting issues

* Fix duplicate spacing constants compilation errors

* Fix height16 scope issue in showChangeLogDialog

* style: auto-fix linting and formatting issues

* Add Fastlane supply metadata validation step

Added a step to validate Fastlane supply metadata in the lint workflow.

* Add Fastlane Supply Metadata validation job

Added a new job to validate Fastlane Supply Metadata in the lint workflow.

* Remove 'go' job from lint workflow

Removed the 'go' job and its associated steps from the lint workflow.

* Enhance nightly workflow with linting and formatting

Add steps to auto-fix linting issues and format code in nightly workflow.

* Enhance CI workflow with linting and formatting steps

Added steps to auto-fix linting issues and format code in CI workflow.

* Add auto-fix linting and formatting steps to workflow

Added steps to auto-fix linting issues and format code before committing changes.

* Delete .github/workflows/lint.yml

* Delete .github/workflows/dependency-review.yml

* Fix updateAppIcon method parameter reference error

* Fix #168

* Fix icons in the app view page

* style: auto-fix linting and formatting issues

* style: auto-fix linting and formatting issues

* Remove grid view from the code

* Re-add grid view from Qama v26.1

* style: auto-fix linting and formatting issues

* Fix typo

* Fix formatting in localization section of README

* Fix grid

* Fix design inconsistency

* style: auto-fix linting and formatting issues

* Fix app.dart

* Delete renovate.json

* style: auto-fix linting and formatting issues

* fix export error

* style: auto-fix linting and formatting issues

* Quick bug fix

* style: auto-fix linting and formatting issues

* Add renovate.json

* chore(deps): update google/osv-scanner-action action to v2.3.3

* chore(deps): update gradle to v9.3.1

* chore(deps): update plugin org.jetbrains.kotlin.android to v2.3.10

* chore(deps): update actions/github-script action to v8

* chore(deps): update actions/upload-artifact action to v7

* chore(deps): update stefanzweifel/git-auto-commit-action action to v7

* Another bugfix

* Update lib/providers/apps_provider.dart

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update BUTTON_MIGRATION_GUIDE.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update lib/examples/refactored_icon_pipeline_example.dart

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update lib/examples/refactored_icon_pipeline_example.dart

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update assets/translations/README.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* chore(deps): update actions/checkout action to v6

* chore(deps): update actions/github-script action to v8

* style: auto-fix linting and formatting issues

* Fix workflows

* chore(deps): update dependency node to v24

* chore(deps): update actions/setup-node action to v6

* Update translations.yml

* chore(deps): update dependency node to v24

* Migrate some design components to the official Flutter ones

* 🌐 Add missing translation keys for export functionality

* Fix workflow

* chore(deps): update actions/checkout action to v6

* style: auto-fix linting and formatting issues

* add about (#196)

* M3 Expressive update (#194)

* M3 Expressive update

* Update lib/main.dart

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* commit

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* chore(deps): update stefanzweifel/git-auto-commit-action action to v7 (#198)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update peter-evans/create-pull-request action to v8 (#197)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

Warning

Rate limit exceeded

@omeritzics has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 31 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bfc699c4-13c7-4811-ae84-7c2e68a3f89f

📥 Commits

Reviewing files that changed from the base of the PR and between aeca22b and 285d6e1.

📒 Files selected for processing (14)
  • .github/workflows/translations.yml
  • android/app/src/main/kotlin/io/github/omeritzics/updatium/MainActivity.kt
  • assets/translations/ar.json
  • assets/translations/en.json
  • assets/translations/es.json
  • assets/translations/it.json
  • assets/translations/ja.json
  • assets/translations/pt.json
  • assets/translations/ru.json
  • assets/translations/zh.json
  • lib/pages/settings.dart
  • lib/providers/apps_provider.dart
  • lib/security/security_settings_provider.dart
  • lib/security/yara_scanner.dart
📝 Walkthrough

Walkthrough

Adds a YARA-based malware scanning system and centralized security settings; integrates scans into APK installation with quarantine support, adds localization for scanner UI, updates settings UI and theme styles, removes several Android-specific integrations, and reshapes pubspec dependencies.

Changes

Cohort / File(s) Summary
Android Manifest
android/AndroidManifest.xml
Added Flutter Embedding v2 meta-data (flutterEmbedding: "2").
Localization Strings
assets/translations/en.json, assets/translations/fr.json, assets/translations/de.json
Added ~31 new keys per language for YARA malware scanner UI: labels, descriptions, threat levels, quarantine controls, update/status messages.
New Security Modules
lib/security/yara_scanner.dart, lib/security/security_settings_provider.dart
Introduced YARAScanner singleton, YARA data models, rule update logic, file scanning, quarantine handling, and SecuritySettingsProvider with persisted settings, scan/update APIs, and logging hooks.
APK Install Flow & Providers
lib/providers/apps_provider.dart, lib/providers/settings_provider.dart, lib/providers/native_provider.dart
AppsProvider now runs malware scans before installation and cleans up infected files; removed DocMan/Safety flows and Android-specific installers; native_provider stops loading Android system font.
Settings & UI
lib/pages/settings.dart, lib/main.dart
Settings page wired to SecuritySettingsProvider, added UI controls (auto-scan/update, interval, update rules), About dialog via PackageInfo; updated input/dropdown styling (radii, padding, font weights, fillColor).
Deep Links & Import Cleanup
lib/pages/home.dart, lib/pages/app.dart, lib/pages/apps.dart, lib/custom_errors.dart
Removed AppLinks integration and unused imports (flutter_markdown_plus, android_package_installer).
Pubspec / Dependencies
pubspec.yaml
Downgraded SDK/Flutter constraints and replaced/removed many dependencies (removed android_package_installer, shizuku_apk_installer, android_system_font, flutter_markdown_plus; added/adjusted various packages, added package_info_plus, crypto).

Sequence Diagram

sequenceDiagram
    participant User
    participant AppsProvider
    participant SecurityProvider as SecuritySettingsProvider
    participant YARAScanner
    participant FS as File System
    participant Logs as Logs Provider

    User->>AppsProvider: installApk(apkPath)
    AppsProvider->>SecurityProvider: scanAPK(apkPath)
    SecurityProvider->>SecurityProvider: Check auto-scan setting
    alt Auto-scan disabled
        SecurityProvider-->>AppsProvider: non-infected result
    else Auto-scan enabled
        SecurityProvider->>YARAScanner: scanFile(apkPath)
        YARAScanner->>YARAScanner: Ensure rules loaded / update if needed
        YARAScanner-->>SecurityProvider: YARAScanResult
        alt Infection detected & quarantine enabled
            SecurityProvider->>FS: _quarantineFile(apkPath)
            FS-->>SecurityProvider: quarantinePath
            SecurityProvider->>Logs: Log quarantine/report
        else No infection
            SecurityProvider->>Logs: Log scan result
        end
        SecurityProvider-->>AppsProvider: YARAScanResult
    end
    alt Malware detected
        AppsProvider->>FS: Cleanup downloaded files
        AppsProvider-->>User: Error (installation blocked)
    else No malware
        AppsProvider->>AppsProvider: proceed with installation (platform-specific)
        AppsProvider-->>User: Installation success
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Ux-ui #246: Modifies lib/pages/settings.dart and translation files; may overlap with settings UI and localization changes.

Poem

🐰🔎
I hop through bytes and lines tonight,
With YARA rules I check each byte,
When threats are found I tuck them tight,
A quarantined burrow, safe and bright,
Hooray — your APKs sleep snug and right!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The pull request title 'feat: In-app malware scanning' directly and accurately describes the main objective of this changeset, which introduces comprehensive YARA-based malware scanning capabilities throughout the application.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch yara-scan
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the application's security posture by integrating a robust in-app malware scanning system using YARA rules. This new capability allows for the automatic detection and handling of malicious APKs, providing users with a safer experience. Alongside this major feature, the project's dependency landscape has been streamlined through the removal of several external packages and updates to existing ones, contributing to a more maintainable and efficient codebase.

Highlights

  • In-App Malware Scanning: Introduced a new in-app malware scanning feature powered by YARA, allowing automatic scanning of downloaded APKs before installation.
  • Security Settings UI: Added new user interface elements and localization strings across German, English, and French for configuring YARA scanner settings, including auto-scan, auto-update, update intervals, and quarantine options.
  • Dependency Refactoring: Performed a significant refactoring of project dependencies, removing several packages such as android_package_installer, android_package_manager, app_links, docman, shizuku_apk_installer, android_system_font, flutter_markdown_plus, and background_fetch. Many remaining dependencies were updated to newer versions.
  • Installation Process Integration: Integrated the YARA malware scanning directly into the APK installation flow, blocking installation if malware is detected and offering quarantine options.
  • UI/UX Enhancements: Updated the visual styling of text input fields and dropdown menus, including changes to border radius, fill color, and font weights for a more modern appearance.
Changelog
  • android/AndroidManifest.xml
    • Added Flutter Android Embedding v2 metadata.
  • assets/translations/de.json
    • Added new German translation strings for YARA scanner settings and descriptions.
  • assets/translations/en.json
    • Added new English translation strings for YARA scanner settings and descriptions.
  • assets/translations/fr.json
    • Added new French translation strings for YARA scanner settings and descriptions.
  • lib/custom_errors.dart
    • Removed android_package_installer import.
  • lib/main.dart
    • Removed background_fetch import.
    • Updated floatingLabelStyle font weight from w500 to w600.
    • Modified inputDecorationTheme for OutlineInputBorder properties including borderRadius, borderSide, fillColor, contentPadding, labelStyle, and floatingLabelStyle.
  • lib/pages/app.dart
    • Removed flutter_markdown_plus import.
  • lib/pages/apps.dart
    • Removed flutter_markdown_plus import.
  • lib/pages/home.dart
    • Removed app_links import and associated deep linking functionality.
  • lib/pages/settings.dart
    • Added package_info_plus and security_settings_provider imports.
    • Removed shizuku_apk_installer import.
    • Introduced _securityProvider and _securityProviderInitialized state variables.
    • Implemented _showAboutDialog, initState, dispose, and _initializeSecurityProvider methods.
    • Added a floating action button to display the 'About' dialog.
    • Removed ShizukuApkInstaller permission check logic.
    • Integrated YARA malware scanner settings UI components.
  • lib/providers/apps_provider.dart
    • Removed android_package_installer, android_package_manager, docman, and shizuku_apk_installer imports.
    • Added security_settings_provider import.
    • Updated http.Request calls to use http.Request explicitly.
    • Simplified getAllInstalledInfo and getInstalledInfo to return null, indicating removal of external package info retrieval.
    • Added _scanAPKForMalware method for pre-installation malware checks.
    • Integrated malware scanning logic before APK installation, including cleanup of infected files.
    • Removed AndroidPackageInstaller and ShizukuApkInstaller installation logic.
  • lib/providers/native_provider.dart
    • Removed android_system_font import and related loadSystemFont functionality.
  • lib/providers/settings_provider.dart
    • Removed docman import.
    • Removed DocMan related functionality for export directory management and permissions.
  • lib/security/security_settings_provider.dart
    • Added a new file defining SecuritySettingsProvider to manage YARA scanner configurations and interactions.
  • lib/security/yara_scanner.dart
    • Added a new file defining YARAScanner for YARA rule management, remote rule updates, and file scanning.
  • pubspec.lock
    • Updated numerous package versions.
    • Removed entries for android_package_installer, android_package_manager, android_system_font, app_links, background_fetch, bcrypt, docman, flutter_lints, flutter_markdown_plus, gtk, hooks, lints, logging, native_toolchain_c, objective_c, pub_semver, shizuku_apk_installer, sqflite_android, sqflite_darwin, sqflite_platform_interface, and yaml.
  • pubspec.yaml
    • Updated Dart SDK and Flutter environment versions.
    • Updated versions for path_provider, flutter_local_notifications, http, material_color_utilities, shared_preferences, url_launcher, path, permission_handler, fluttertoast, crypto, device_info_plus, file_picker, animations, share_plus, sqflite, equations, flex_color_picker, battery_plus, flutter_foreground_task.
    • Added package_info_plus dependency.
    • Removed android_package_installer, android_package_manager, docman, bcrypt, app_links, background_fetch, android_system_font, shizuku_apk_installer, flutter_lints, and flutter_markdown_plus dependencies.
Activity
  • New YARA-powered malware scanning functionality has been introduced.
  • Extensive dependency cleanup and version updates were performed.
  • User interface for security settings has been added and localized.
  • The APK installation process now includes a malware scan step.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant new feature: in-app malware scanning powered by YARA. It also includes a substantial refactoring that removes several dependencies and cleans up the codebase. While the new security feature is a great addition, the current implementation of the YARA scanner is fundamentally flawed and does not provide the expected level of security. Additionally, the refactoring appears to have broken core application functionality, such as installing APKs. There are also concerns about resource management and performance that should be addressed.

Comment on lines 500 to 502
Future<List<PackageInfo>> getAllInstalledInfo() async {
return await pm.getInstalledPackages(flags: packageInfoFlags) ?? [];
return [];
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This function, along with getInstalledInfo and installApk, has been stubbed out and no longer interacts with the Android package manager. This effectively removes the application's core functionality of installing and managing apps. For example, installApk now hardcodes code = 'not_implemented', preventing any installations.

This is a critical regression. If this is an intentional part of a larger refactoring, it should be clearly documented. Otherwise, this needs to be fixed before merging.

}

/// Main YARA Scanner Class
class YARAScanner {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The current implementation of YARAScanner is not a true YARA engine. It appears to be a custom, simplified string and hex pattern matcher that parses YARA rule files. This is fundamentally different from how the actual YARA engine works, which involves compiling rules into a more efficient format and using advanced pattern matching algorithms.

This implementation is misleading as the feature is advertised as being 'powered by YARA', and it is likely to be ineffective at detecting malware compared to a real YARA engine. This could create a false sense of security for users.

Recommendation: Instead of a custom implementation, please integrate the actual YARA library. This can be done using Flutter's FFI (Foreign Function Interface) to call the native YARA C library. There might also be existing packages on pub.dev that provide these bindings.

Comment on lines +180 to +184
void dispose() {
// Cancel auto-update timer to prevent memory leaks
// Note: We don't dispose the singleton here as it might be used by other instances
// Instead, callers should call YARAScanner.disposeInstance() when the app is shutting down
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The dispose method does not clean up the Timer created in the YARAScanner singleton for auto-updates. The comment indicates this is intentional, but there is no corresponding call to YARAScanner.disposeInstance() when the application is terminated. This will result in a resource leak, with the timer continuing to run in the background even when it's no longer needed.

Recommendation: The lifecycle of the YARAScanner singleton should be managed properly. The dispose method here should call a method on the scanner to cancel the timer, or there should be a clear mechanism to dispose of the singleton when the app is destroyed.

}

/// Scan APK for malware before installation
Future<bool> _scanAPKForMalware(String apkPath, {List<String>? additionalApkPaths}) async {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The _scanAPKForMalware method creates a new instance of SecuritySettingsProvider every time it's called. The provider's creation (SecuritySettingsProvider.create()) involves asynchronous operations and I/O (reading SharedPreferences and getting application directories), making this approach inefficient, especially if scans are frequent.

Recommendation: To improve performance, SecuritySettingsProvider should be managed as a longer-lived object. Consider providing it as a singleton or using a dependency injection framework like provider to manage its lifecycle, so it's created only once.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 CI Build Failed

The automated build process failed. Please review the build logs and fix the issues before requesting another review.

Next steps:

  1. Check the build logs for specific errors
  2. Fix the identified issues
  3. Push your fixes to this branch
  4. The CI will automatically re-run

Once the build passes, this review will be dismissed automatically.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
lib/providers/settings_provider.dart (1)

421-439: ⚠️ Potential issue | 🟠 Major

Export directory selection is effectively broken now.

pickExportDir() no longer persists a new directory, and getExportDir() now returns whatever URI was last stored without checking that it is still usable. lib/providers/apps_provider.dart and lib/pages/import_export.dart still depend on both behaviors, so the picker/export UI can appear to work while writes keep using a stale location or fail later.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/providers/settings_provider.dart` around lines 421 - 439, getExportDir
currently just parses the stored 'exportDir' string without validating it, and
pickExportDir no longer persists a newly picked directory (nor clears it on
remove), causing stale or unusable export locations; fix by updating
pickExportDir to (a) invoke the platform picker/code-path that obtains a new
Uri, persist its string into prefs under 'exportDir' (and clear prefs when
remove==true), and return/update any in-memory state, and (b) update
getExportDir to validate the stored Uri (e.g., check the Uri parses, and verify
existence/writeability or access via the same storage API used for exporting)
and if validation fails return null (and clear the stale prefs entry), so
callers in apps_provider.dart and import_export.dart always receive a current
usable directory via getExportDir and pickExportDir.
lib/pages/home.dart (1)

147-259: ⚠️ Potential issue | 🟠 Major

This removes all working updatium:// deep-link handling.

initDeepLinks() no longer reads the initial intent or subscribes to link events, while android/app/src/main/AndroidManifest.xml still exposes the updatium scheme. Share/import links will now open the app and then be ignored.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/pages/home.dart` around lines 147 - 259, initDeepLinks currently defines
interpretLink/goToAddApp/goToExistingApp but never hooks them up to platform
intents, so updatium:// links are ignored; restore initial intent reading and a
link-event subscription that invokes interpretLink(Uri) for incoming links, and
ensure the subscription is cancelled on widget dispose. Specifically, inside
initDeepLinks add code to (1) read the initial link/intent and call
interpretLink(Uri.parse(...)) if present, (2) subscribe to the link stream (or
AppLinks/uni_links equivalent) and call interpretLink for each event, and (3)
save and cancel the StreamSubscription on dispose; keep the existing helper
functions (goToAddApp, goToExistingApp, interpretLink) and reuse them when
handling both initial and subsequent links.
pubspec.yaml (1)

22-76: ⚠️ Potential issue | 🔴 Critical

Incompatible API usage detected against declared minimums—build will fail.

The lowered minimums are incompatible with the codebase:

  • Flutter 3.19.0: Does not include Color.withValues (added 3.27.0), WidgetStateProperty (3.22.0), PredictiveBackPageTransitionsBuilder (3.22.0), or year2023 theme flags (3.29.0). The repo uses all of these across lib/main.dart, lib/pages/settings.dart, lib/pages/app.dart, and elsewhere.
  • share_plus 7.0.0: Does not support fileNameOverrides parameter in Share.shareXFiles(...) (added in 10.0.0). Used in lib/pages/apps.dart:1364.
  • flutter_foreground_task 8.0.0: Does not include TaskStarter callback or ForegroundServiceTypes (both added in 8.9.0). Used in lib/main.dart:119 and lib/main.dart:250.

Require minimum versions: Flutter ≥3.29.0, share_plus ≥10.0.0, flutter_foreground_task ≥8.9.0.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pubspec.yaml` around lines 22 - 76, Update the package minimums in
pubspec.yaml to match APIs used: set the Dart/Flutter SDK constraint to require
Flutter ≥3.29.0 (replace the current sdk/flutter lines so Flutter is
">=3.29.0"), bump share_plus to at least ^10.0.0 to get the fileNameOverrides
parameter for Share.shareXFiles, and bump flutter_foreground_task to at least
^8.9.0 to get TaskStarter and ForegroundServiceTypes; this aligns the declared
minimums with usages of Color.withValues, WidgetStateProperty,
PredictiveBackPageTransitionsBuilder, the year2023 theme flags,
Share.shareXFiles(fileNameOverrides: ...), TaskStarter, and
ForegroundServiceTypes.
lib/pages/settings.dart (1)

828-838: ⚠️ Potential issue | 🟠 Major

Remove or disable the dead Shizuku toggle.

Both branches force settingsProvider.useShizuku = false, so this switch can never stay enabled. lib/providers/apps_provider.dart also rejects the Shizuku path now, which leaves an interactive control with no working behavior behind it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/pages/settings.dart` around lines 828 - 838, The Switch for Shizuku is
dead (both branches set settingsProvider.useShizuku = false) and should be
removed or disabled: remove or replace the Switch widget (the Switch and its
onChanged handler around Flexible/Text(tr('useShizuku')) and the references to
settingsProvider.useShizuku) or make it clearly disabled by setting value: false
and onChanged: null and optionally add a subtitle/tooltip explaining it’s
unsupported; also remove any dead branching logic that attempted to toggle
Shizuku so no unused code referencing settingsProvider.useShizuku remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@android/AndroidManifest.xml`:
- Around line 1-4: The top-level android/AndroidManifest.xml is dead config and
duplicates the flutterEmbedding meta-data; remove this duplicate file or move
the <meta-data android:name="flutterEmbedding" android:value="2" /> entry into
the real app manifest used by Gradle (the manifest merged from
android/app/src/main/AndroidManifest.xml under the <application> element) so
only the canonical manifest contains the flutterEmbedding meta-data.

In `@assets/translations/de.json`:
- Around line 31-64: New YARA/security translation keys (e.g.,
"yaraMalwareScanner", "yaraScannerDescription", "enableAutoScan",
"enableAutoScanDescription", "enableAutoUpdate", "enableAutoUpdateDescription",
"updateInterval", "updateIntervalDescription", "threatLevelFilter",
"quarantineInfected", "quarantineInfectedDescription", etc.) were only added to
de.json causing the Translation Management CI to fail; add the same keys to
every locale file under assets/translations that lib/main.dart declares as
supported (not just en/de/fr) — either with proper localized strings or safe
placeholders (English or the de values) so no locale is left missing these keys
— and ensure the JSON structure and commas are valid in each file.

In `@assets/translations/en.json`:
- Around line 31-61: Add the new translation keys introduced in this diff (for
example: "yaraMalwareScanner", "yaraScannerDescription", "securitySettings",
"enableAutoScan", "enableAutoScanDescription", "enableAutoUpdate",
"enableAutoUpdateDescription", "updateInterval", "updateIntervalDescription",
"hours", "threatLevelFilter", "threatLevelFilterDescription", "level1",
"lowThreat", "level2", "mediumThreat", "level3", "highThreat",
"quarantineSettings", "quarantineInfected", "quarantineInfectedDescription",
"viewQuarantine", "viewQuarantineDescription", "databaseInformation",
"lastUpdate", "rulesVersion", "updateNow", "updating",
"rulesUpdatedSuccessfully", "rulesUpdateFailed", "quarantineViewComingSoon")
into every other locale file so the translation-management job no longer reports
missing keys; for each locale add the exact key names with appropriate
translated strings (or sensible placeholder values such as the English text) so
all locales mirror the en.json keys before merging.
- Around line 31-32: The translation copy overstates the
implementation—lib/security/yara_scanner.dart implements a basic custom matcher,
not a full YARA engine—so update the strings for "yaraMalwareScanner" and
"yaraScannerDescription" to remove "Powered by YARA" and "industry-standard"
phrasing and instead describe it as a basic YARA-inspired/custom rule matcher
that provides additional scanning but does not guarantee full YARA compatibility
or 100% detection; make the language accurate and include a short user-facing
disclaimer about limitations.

In `@lib/pages/settings.dart`:
- Around line 916-923: The DropdownMenuItem labels hardcode "hours" causing "1
hours" — update the label generation in the DropdownButton<int> /
DropdownMenuItem<int> map so it uses the correct singular/plural translation
(e.g., call the app's pluralization API or choose tr('hour') when hours == 1 and
tr('hours') otherwise) when building the child Text for each hours value; keep
the existing use of _securityProviderInitialized and
_securityProvider.getUpdateInterval() unchanged while only changing the label
expression.

In `@lib/providers/apps_provider.dart`:
- Around line 500-516: The placeholder implementations of getAllInstalledInfo
and getInstalledInfo break app-detection; replace them with real package-manager
queries: implement getAllInstalledInfo to return the list of installed
PackageInfo objects from the platform package manager and implement
getInstalledInfo(String? packageName, {bool printErr = true}) to look up and
return the PackageInfo for the given packageName (or null if not found),
preserving the existing try/catch and honoring printErr when logging errors;
ensure you use the same PackageInfo type expected downstream and do not return
[]/null unconditionally so loadApps(), version reconciliation, downgrade checks,
and silent-install logic receive real data.
- Around line 2353-2355: The export feature has been short-circuited:
DocMan-related export paths return null (silently no-op) so neither auto-export
nor manual export persist data; restore the original persistence instead of
returning null by removing the early returns in the DocMan export handlers and
invoking the existing persistence/save routine used by the export flow (the same
code path used by import/export persistence), ensuring both the auto-export and
manual export functions call that persistence method and return its result
rather than null.
- Around line 1058-1065: The variable code is declared as int? but is being
assigned the string 'not_implemented'; replace those string assignments by
throwing immediately when installation is unsupported: inside the branches that
reference AndroidPackageInstaller and ShizukuApkInstaller (the blocks guarded by
settingsProvider.useShizuku), throw a descriptive exception (e.g.,
UnsupportedError or InstallError) instead of assigning a sentinel string so
callers never receive a non-int; leave any remaining integer-returning paths and
the subsequent comparisons (code != 0, code != 3) and InstallError(code)
expecting an int intact.

In `@lib/providers/native_provider.dart`:
- Around line 13-17: The loadSystemFont() function currently sets
_systemFontLoaded = true without actually adding or loading any font, causing
'SystemFont' to be undefined and preventing retries; update loadSystemFont()
(and related FontLoader usage) to either 1) call fontLoader.addFont(...) with
the correct asset/ByteData for the system font and then await fontLoader.load(),
or 2) if the system font is no longer supported, remove the fake success path
and clear the useSystemFont flow (avoid setting _systemFontLoaded = true) so
main.dart's theme fallback to 'SystemFont' doesn't silently fail; reference
loadSystemFont, _systemFontLoaded, and the FontLoader('SystemFont') instance
when making the change.

In `@lib/security/security_settings_provider.dart`:
- Around line 78-80: The scanAPK logic never applies the configured threshold
from getThreatLevelFilter(), so result.matches must be filtered by threat level
before deciding to block/quarantine; update the scanAPK function to read int
threshold = getThreatLevelFilter() and compute filteredMatches =
result.matches.where(match => match.severity >= threshold) (or use the correct
property name on the match object), then use filteredMatches for all downstream
decisions and reporting (e.g., blocking/quarantining, notifications, and
returned results) so the threshold setting actually controls which detections
trigger actions; apply the same filter logic to both places where scanAPK
evaluates result.matches.
- Around line 54-76: The setters setAutoUpdateEnabled and setUpdateInterval
currently only replace the config via YARAScanner.getInstance(_config) but do
not reconfigure the running scanner’s timers; after updating _config and
swapping the instance you should reinitialize the scanner so its auto-update
timer is started/stopped with the new settings—call the scanner reconfiguration
routine (e.g., await _scanner.initialize() or the scanner's restart/reconfigure
method) after assigning _scanner in both setAutoUpdateEnabled and
setUpdateInterval so the running schedule reflects the new config.

In `@lib/security/yara_scanner.dart`:
- Around line 116-144: YARARule.fromString currently collapses an entire .yar
file into one synthetic YARARule, merging metadata across multiple rule blocks;
change the API to parse and return all rules found: implement a parser in
YARARule.fromString (or add YARARules.fromString/parseMultiple) that iterates
the file, detects each "rule <name>" block boundary, collects metadata (name,
author, description, tags, content) per rule, and produces a List<YARARule> (or
an Iterable) rather than a single instance; update callers of
YARARule.fromString to handle multiple rules (or provide a convenience wrapper
for single-rule usage) and ensure the rule content for each YARARule contains
only that block's text so scanning/reporting yields one match object per rule.
- Around line 355-390: The scanner currently only extracts `{ ... }` definitions
and always utf8.encodes the extracted text so quoted strings are skipped and hex
falls back never triggers; update the parsing in the loop that builds strings
(referencing ruleLines and strings) and the later block that finds the match
(stringPattern, stringMatch, searchString, searchBytes, rule.content) to
distinguish three cases: 1) quoted strings (starts with " or ') — strip quotes
and use utf8.encode(searchString), 2) brace or token hex sequences (e.g. "{6A
40}" or "6A 40 68") — detect via a regex like r'^[0-9A-Fa-f\s]+' or presence of
braces and parse hex pairs into bytes, and 3) default text — utf8.encode; ensure
the initial extraction also captures quoted string definitions (e.g.
r'\$(\w+)\s*=\s*"([^"]+)"' and similar) so stringPattern/stringMatch will locate
the correct content in rule.content before converting to searchBytes.
- Around line 183-191: initialize() currently only loads rules from disk and
starts the timer which means fresh installs scan with zero rules; after await
_loadRules() check whether any rules were actually loaded (e.g., rules directory
or in-memory rule list is empty) and if so trigger the same immediate update
routine that _startAutoUpdate schedules (invoke the function the timer would
call — the existing rule-fetch/update method used inside _startAutoUpdate)
before returning; keep cancelling _updateTimer and still start the periodic
timer when config.enableAutoUpdate is true so bootstrapped rules are available
for the first scan.

---

Outside diff comments:
In `@lib/pages/home.dart`:
- Around line 147-259: initDeepLinks currently defines
interpretLink/goToAddApp/goToExistingApp but never hooks them up to platform
intents, so updatium:// links are ignored; restore initial intent reading and a
link-event subscription that invokes interpretLink(Uri) for incoming links, and
ensure the subscription is cancelled on widget dispose. Specifically, inside
initDeepLinks add code to (1) read the initial link/intent and call
interpretLink(Uri.parse(...)) if present, (2) subscribe to the link stream (or
AppLinks/uni_links equivalent) and call interpretLink for each event, and (3)
save and cancel the StreamSubscription on dispose; keep the existing helper
functions (goToAddApp, goToExistingApp, interpretLink) and reuse them when
handling both initial and subsequent links.

In `@lib/pages/settings.dart`:
- Around line 828-838: The Switch for Shizuku is dead (both branches set
settingsProvider.useShizuku = false) and should be removed or disabled: remove
or replace the Switch widget (the Switch and its onChanged handler around
Flexible/Text(tr('useShizuku')) and the references to
settingsProvider.useShizuku) or make it clearly disabled by setting value: false
and onChanged: null and optionally add a subtitle/tooltip explaining it’s
unsupported; also remove any dead branching logic that attempted to toggle
Shizuku so no unused code referencing settingsProvider.useShizuku remains.

In `@lib/providers/settings_provider.dart`:
- Around line 421-439: getExportDir currently just parses the stored 'exportDir'
string without validating it, and pickExportDir no longer persists a newly
picked directory (nor clears it on remove), causing stale or unusable export
locations; fix by updating pickExportDir to (a) invoke the platform
picker/code-path that obtains a new Uri, persist its string into prefs under
'exportDir' (and clear prefs when remove==true), and return/update any in-memory
state, and (b) update getExportDir to validate the stored Uri (e.g., check the
Uri parses, and verify existence/writeability or access via the same storage API
used for exporting) and if validation fails return null (and clear the stale
prefs entry), so callers in apps_provider.dart and import_export.dart always
receive a current usable directory via getExportDir and pickExportDir.

In `@pubspec.yaml`:
- Around line 22-76: Update the package minimums in pubspec.yaml to match APIs
used: set the Dart/Flutter SDK constraint to require Flutter ≥3.29.0 (replace
the current sdk/flutter lines so Flutter is ">=3.29.0"), bump share_plus to at
least ^10.0.0 to get the fileNameOverrides parameter for Share.shareXFiles, and
bump flutter_foreground_task to at least ^8.9.0 to get TaskStarter and
ForegroundServiceTypes; this aligns the declared minimums with usages of
Color.withValues, WidgetStateProperty, PredictiveBackPageTransitionsBuilder, the
year2023 theme flags, Share.shareXFiles(fileNameOverrides: ...), TaskStarter,
and ForegroundServiceTypes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 29b0bea5-5302-4408-9eaf-d47daeb09029

📥 Commits

Reviewing files that changed from the base of the PR and between e86adb6 and 73b615b.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • android/AndroidManifest.xml
  • assets/translations/de.json
  • assets/translations/en.json
  • assets/translations/fr.json
  • lib/custom_errors.dart
  • lib/main.dart
  • lib/pages/app.dart
  • lib/pages/apps.dart
  • lib/pages/home.dart
  • lib/pages/settings.dart
  • lib/providers/apps_provider.dart
  • lib/providers/native_provider.dart
  • lib/providers/settings_provider.dart
  • lib/security/security_settings_provider.dart
  • lib/security/yara_scanner.dart
  • pubspec.yaml
💤 Files with no reviewable changes (3)
  • lib/pages/apps.dart
  • lib/pages/app.dart
  • lib/custom_errors.dart

Comment on lines +31 to +64
"yaraMalwareScanner": "Automatische Malware-Erkennung (Powered by YARA)",
"yaraScannerDescription": "Branchenstandardmäßige Malware-Erkennung mit YARA-kompatiblen Regeln für umfassenden Schutz vor Viren, Trojanern und anderen Bedrohungen. Kein Scanner kann 100% Erkennung garantieren, bietet aber starken Schutz vor bekannter Malware. Die Verantwortung für die sichere App-Nutzung liegt letztlich beim Benutzer.",
"securitySettings": "Sicherheitseinstellungen",
"xIsTrackOnly": "{} ist nur zur Nachverfolgung",
"source": "Quelle",
"app": "App",
"enableAutoScan": "Automatische Scan aktivieren",
"enableAutoScanDescription": "Heruntergeladene APKs automatisch auf Malware scannen, vor der Installation",
"enableAutoUpdate": "Automatische Updates aktivieren",
"enableAutoUpdateDescription": "Malware-Definitions-Datenbank automatisch aktualisieren",
"updateInterval": "Update-Intervall",
"updateIntervalDescription": "Wie oft nach neuen Malware-Definitionen gesucht werden soll",
"hours": "Stunden",
"threatLevelFilter": "Bedrohungsstufen-Filter",
"threatLevelFilterDescription": "Mindestbedrohungsstufe für Warnungen",
"level1": "Stufe 1",
"lowThreat": "Niedrige Bedrohung",
"level2": "Stufe 2",
"mediumThreat": "Mittlere Bedrohung",
"level3": "Stufe 3",
"highThreat": "Hohe Bedrohung",
"quarantineSettings": "Quarantäne-Einstellungen",
"quarantineInfected": "Infizierte Dateien quarantänen",
"quarantineInfectedDescription": "Erkannte Malware zur Sicherheit in Quarantäne verschieben",
"viewQuarantine": "Quarantäne anzeigen",
"viewQuarantineDescription": "Quarantänierte Dateien verwalten",
"databaseInformation": "Datenbank-Informationen",
"lastUpdate": "Letzte Aktualisierung",
"rulesVersion": "Regeln-Version",
"updateNow": "Jetzt aktualisieren",
"updating": "Aktualisiere...",
"rulesUpdatedSuccessfully": "Malware-Definitionen erfolgreich aktualisiert",
"rulesUpdateFailed": "Fehler beim Aktualisieren der Malware-Definitionen",
"quarantineViewComingSoon": "Quarantäne-Ansicht kommt bald",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

These new YARA keys still need to land in the rest of assets/translations/.

The Translation Management job is already failing, and lib/main.dart declares many supported locales beyond en/de/fr. Adding the new security keys in only a subset of locale files keeps CI red and leaves the remaining locales on fallback/missing strings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/translations/de.json` around lines 31 - 64, New YARA/security
translation keys (e.g., "yaraMalwareScanner", "yaraScannerDescription",
"enableAutoScan", "enableAutoScanDescription", "enableAutoUpdate",
"enableAutoUpdateDescription", "updateInterval", "updateIntervalDescription",
"threatLevelFilter", "quarantineInfected", "quarantineInfectedDescription",
etc.) were only added to de.json causing the Translation Management CI to fail;
add the same keys to every locale file under assets/translations that
lib/main.dart declares as supported (not just en/de/fr) — either with proper
localized strings or safe placeholders (English or the de values) so no locale
is left missing these keys — and ensure the JSON structure and commas are valid
in each file.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (3)
lib/providers/apps_provider.dart (3)

500-516: ⚠️ Potential issue | 🔴 Critical

Restore real installed-package queries (placeholders break app state).

getAllInstalledInfo() and getInstalledInfo() now return []/null unconditionally, so installed apps are treated as uninstalled. That breaks install-state reconciliation, downgrade checks, and silent-install eligibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/providers/apps_provider.dart` around lines 500 - 516, The placeholders in
getAllInstalledInfo() and getInstalledInfo() are breaking app state; restore
their real implementations by replacing the empty returns with the actual
platform queries: have getAllInstalledInfo() asynchronously fetch and map
installed packages into List<PackageInfo> (e.g., using the platform package API
originally used in this file) and have getInstalledInfo(String? packageName,
{bool printErr = true}) query for a single package by name, returning a
PackageInfo or null; keep the existing try/catch behavior, ensure errors are
logged when printErr is true, and return the proper types instead of []/null so
install-state reconciliation, downgrade checks, and silent-install eligibility
work correctly.

1058-1074: ⚠️ Potential issue | 🔴 Critical

Installation path has a hard type error (int? assigned String).

code is int?, but both branches assign 'not_implemented' (Line 1061, Line 1064). Subsequent integer comparisons and InstallError(code) are incompatible and break this path.

#!/bin/bash
set -euo pipefail

# Verify the mismatched assignments in installApk()
sed -n '1056,1076p' lib/providers/apps_provider.dart

# Verify InstallError usage/signature context expects numeric code
rg -n -C3 'class InstallError|InstallError\(' lib
Suggested fix
-    int? code;
-    if (!settingsProvider.useShizuku) {
-      // AndroidPackageInstaller functionality removed
-      code = 'not_implemented';
-    } else {
-      // ShizukuApkInstaller functionality removed
-      code = 'not_implemented';
-    }
+    throw UpdatiumError(tr('functionNotImplemented'));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/providers/apps_provider.dart` around lines 1058 - 1074, The variable code
is declared as int? but is being assigned the String 'not_implemented'; change
those assignments to an integer sentinel (e.g., define a constant like
kNotImplemented = -2 and assign that) so the comparisons (code != 0 && code !=
3) and the InstallError(code) call remain type-correct; update any related
conditional logic in the same block (the branches that previously set
'not_implemented') to use the integer constant and ensure InstallError is
invoked with an int.

2353-2355: ⚠️ Potential issue | 🟠 Major

Export is currently a silent no-op in both auto and manual paths.

Both branches return null before persistence, so export appears available but does nothing.

Also applies to: 2373-2374

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/providers/apps_provider.dart`:
- Around line 939-982: The helper _scanAPKForMalware currently returns false for
both infections and scanner failures, losing distinction; change it to return a
structured result (e.g., an enum ScanOutcome { clean, infected, scannerError }
or a small class ScanResult { ScanOutcome outcome; String? message;
List<String>? matches; }) instead of Future<bool>, populate outcome and
diagnostic fields at each exit (primary scan error -> scannerError with error
message, primary scan infected -> infected with match names, additional APK
outcomes set similarly, final successful path -> clean), and update all callers
of _scanAPKForMalware to handle the new structured result so installation flow
and telemetry can differentiate infected vs scanner-unavailable cases.
- Around line 1361-1363: The code throws
UpdatiumError(tr('shizukuNotSupported')) after download/processing has started,
causing wasted network/disk work; move the Shizuku support check earlier into
the preflight path (e.g., add a check in preflightChecks or the function that
runs before downloads) or change the silent-install eligibility function
(isSilentInstallEligible / similar) to return false when Shizuku is unsupported
so the flow never begins the download/processing; update references to
ShizukuApkInstaller removal accordingly and ensure the early check throws or
prevents silent installs before any expensive work starts.
- Around line 1021-1036: Replace the hard-coded translation lookup tr('Security
scan detected malware. Installation blocked for safety.') with a stable i18n key
(for example tr('securityScanBlocked')) in the block that throws UpdatiumError
when _scanAPKForMalware returns false; update the locales/translation resource
files to include the new key mapping to the full sentence for all supported
locales and ensure any tests or callers expecting the old literal are updated to
use the new key.

---

Duplicate comments:
In `@lib/providers/apps_provider.dart`:
- Around line 500-516: The placeholders in getAllInstalledInfo() and
getInstalledInfo() are breaking app state; restore their real implementations by
replacing the empty returns with the actual platform queries: have
getAllInstalledInfo() asynchronously fetch and map installed packages into
List<PackageInfo> (e.g., using the platform package API originally used in this
file) and have getInstalledInfo(String? packageName, {bool printErr = true})
query for a single package by name, returning a PackageInfo or null; keep the
existing try/catch behavior, ensure errors are logged when printErr is true, and
return the proper types instead of []/null so install-state reconciliation,
downgrade checks, and silent-install eligibility work correctly.
- Around line 1058-1074: The variable code is declared as int? but is being
assigned the String 'not_implemented'; change those assignments to an integer
sentinel (e.g., define a constant like kNotImplemented = -2 and assign that) so
the comparisons (code != 0 && code != 3) and the InstallError(code) call remain
type-correct; update any related conditional logic in the same block (the
branches that previously set 'not_implemented') to use the integer constant and
ensure InstallError is invoked with an int.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0ea4faac-9e2a-4049-b368-28e46aaa3113

📥 Commits

Reviewing files that changed from the base of the PR and between 73b615b and aeca22b.

📒 Files selected for processing (3)
  • lib/main.dart
  • lib/pages/apps.dart
  • lib/providers/apps_provider.dart
💤 Files with no reviewable changes (1)
  • lib/pages/apps.dart
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/main.dart

Comment on lines +939 to +982
/// Scan APK for malware before installation
Future<bool> _scanAPKForMalware(String apkPath, {List<String>? additionalApkPaths}) async {
SecuritySettingsProvider? securityProvider;
try {
securityProvider = await SecuritySettingsProvider.create();
await securityProvider.initialize();
final scanResult = await securityProvider.scanAPK(apkPath);

if (scanResult.error != null) {
logs.add('Security scan error for primary APK: ${scanResult.error}');
return false;
}

if (scanResult.isInfected) {
logs.add(
'Security scan detected malware in APK: ${scanResult.matches.map((m) => m.ruleName).join(', ')}',
);
return false;
}

if (additionalApkPaths != null) {
for (final additionalApkPath in additionalApkPaths) {
final additionalScanResult = await securityProvider.scanAPK(additionalApkPath);

if (additionalScanResult.error != null) {
logs.add('Security scan error for additional APK: ${additionalScanResult.error}');
return false;
}

if (additionalScanResult.isInfected) {
logs.add('Security scan detected malware in additional APK: ${additionalScanResult.matches.map((m) => m.ruleName).join(', ')}');
return false;
}
}
}

return true;
} catch (e) {
logs.add('Security scan failed: $e');
return false; // Block installation on scan failure
} finally {
securityProvider?.dispose();
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t collapse malware and scan-failure into a single boolean.

This helper returns false for both infection and scanner errors (Line 947 and Line 976), so callers can’t distinguish “infected APK” from “scanner unavailable/error”. Return a structured status so install flow can show correct user messaging and telemetry.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/providers/apps_provider.dart` around lines 939 - 982, The helper
_scanAPKForMalware currently returns false for both infections and scanner
failures, losing distinction; change it to return a structured result (e.g., an
enum ScanOutcome { clean, infected, scannerError } or a small class ScanResult {
ScanOutcome outcome; String? message; List<String>? matches; }) instead of
Future<bool>, populate outcome and diagnostic fields at each exit (primary scan
error -> scannerError with error message, primary scan infected -> infected with
match names, additional APK outcomes set similarly, final successful path ->
clean), and update all callers of _scanAPKForMalware to handle the new
structured result so installation flow and telemetry can differentiate infected
vs scanner-unavailable cases.

Comment on lines +1361 to 1363
// ShizukuApkInstaller functionality removed
throw UpdatiumError(tr('shizukuNotSupported'));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Shizuku unsupported is detected too late (after expensive work).

Throwing shizukuNotSupported here happens after download/processing has already started, causing avoidable network/disk work and noisy failures. Gate this earlier in the preflight path (or make silent-install eligibility return false when Shizuku install is unsupported).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/providers/apps_provider.dart` around lines 1361 - 1363, The code throws
UpdatiumError(tr('shizukuNotSupported')) after download/processing has started,
causing wasted network/disk work; move the Shizuku support check earlier into
the preflight path (e.g., add a check in preflightChecks or the function that
runs before downloads) or change the silent-install eligibility function
(isSilentInstallEligible / similar) to return false when Shizuku is unsupported
so the flow never begins the download/processing; update references to
ShizukuApkInstaller removal accordingly and ensure the early check throws or
prevents silent installs before any expensive work starts.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@omeritzics omeritzics changed the title feat: In-app malware scanning (powered by YARA) feat: In-app malware scanning Mar 15, 2026
@omeritzics omeritzics linked an issue Mar 17, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security Improvement

1 participant