dotanuki-labs/android-archives-watchdog

GitHub: dotanuki-labs/android-archives-watchdog

一款专注Android发布包安全左移的CLI工具,通过基线对比机制检测Manifest中权限和组件的敏感变更。

Stars: 14 | Forks: 0

# Android Archives Watchdog 🐶 [![ktlint](https://img.shields.io/badge/code%20style-%E2%9D%A4-FF4081.svg)](https://ktlint.github.io/) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/ef1e204d3c143715.svg)](https://github.com/dotanuki-labs/android-archives-watchdog/actions/workflows/ci.yaml) [![License](https://img.shields.io/github/license/dotanuki-labs/norris)](https://choosealicense.com/licenses/mit) ## 概述 `aaw` 是一个命令行工具,其功能介于 [apkanalyzer](https://developer.android.com/tools/apkanalyzer) 和 [bundletool](https://developer.android.com/tools/bundletool) 之间。 该工具旨在帮助检测发布归档文件(`.apk` 或 `.aab`)中新引入的 Android 框架 组件和权限,特别是那些由第三方项目依赖项引入的传递依赖,遵循“shift-left(左移)”理念。 `aaw` 以 [truly-executable](https://skife.org/java/unix/2011/06/20/really_executable_jars.html) [fatjar](https://gradleup.com/shadow) 形式分发,并且 已在 Unix 环境下针对 `jdk17` 和 `jdk21` 进行了测试。此外,本项目针对以下在 Github 上公开发布开源版本的 Android 产品进行了端到端测试: - [DuckDuckGo](https://github.com/duckduckgo/Android) - [ProntonMail](https://github.com/ProtonMail/proton-mail-android) - [WooCommerce](https://github.com/woocommerce/woocommerce-android) - [Mozilla Firefox](https://github.com/mozilla-mobile/firefox-android) ## 环境要求 此工具需要 `jdk17` 或更新版本以及有效的 Android SDK 安装。`aaw` 在定位您的 Android SDK 安装文件夹时会检查以下环境变量: - `$ANDROID_HOME` - `$ANDROID_SDK` - `$ANDROID_SDK_HOME` ## 安装说明 您可以直接从 [Github releases](https://github.com/dotanuki-labs/android-archives-watchdog/releases) 获取可执行文件。 将其解压并添加到您的 `$PATH` 中。 此外,还有一个 [asdf-plugin](https://github.com/dotanuki-labs/asdf-aaw) 可供使用。 ## 使用说明 以下代码片段使用 [ProntonMail](https://github.com/ProtonMail/proton-mail-android) 的发布版本作为示例,特别是版本 [3.0.7](https://github.com/ProtonMail/proton-mail-android/releases/tag/3.0.7)(2022 年 11 月)和 [3.0.17](https://github.com/ProtonMail/proton-mail-android/releases/tag/3.0.17)(2023 年 10 月) 每个命令均支持 `.apk` 和 `.aab` 格式的归档文件。 ### 从 Android 归档文件获取概览 ``` $> aaw overview -a tmp/ProtonMail-3.0.7.apk ┌────────────────────────────┬───────────────────────┐ │ Attribute │ Evaluation │ ├────────────────────────────┼───────────────────────┤ │ Application Id │ ch.protonmail.android │ ├────────────────────────────┼───────────────────────┤ │ Minimum SDK │ 23 │ ├────────────────────────────┼───────────────────────┤ │ Target SDK │ 31 │ ├────────────────────────────┼───────────────────────┤ │ Total Used Features │ 2 │ ├────────────────────────────┼───────────────────────┤ │ Total Manifest permissions │ 14 │ ├────────────────────────────┼───────────────────────┤ │ Dangerous permissions │ Yes │ ├────────────────────────────┼───────────────────────┤ │ Activities │ 54 │ ├────────────────────────────┼───────────────────────┤ │ Services │ 14 │ ├────────────────────────────┼───────────────────────┤ │ Broadcast Receivers │ 15 │ ├────────────────────────────┼───────────────────────┤ │ Content Providers │ 4 │ └────────────────────────────┴───────────────────────┘ ``` 这在功能上模仿了 `apkanalyser`,并支持 `--json` 开关以用于自动化目的。 ### 从 Android 归档文件生成基线 ``` $> aaw generate --archive=tmp/ProtonMail-3.0.7.apk Baseline available at : ch.protonmail.android.toml ``` 此命令将在当前目录中生成一个 `.toml` 文件,该文件旨在纳入您的 VCS(版本控制系统)。此 `toml` 文件跟踪相关合并后 `AndroidManifest.xml` 中的部分信息,即: - [Application Permissions](https://developer.android.com/guide/topics/manifest/manifest-intro#perms) - [Device Compatibility](https://developer.android.com/guide/topics/manifest/manifest-intro#compatibility) - [Activities, Services, Content Providers and Broadcast Receivers](https://developer.android.com/guide/topics/manifest/manifest-intro#components) 或者,您可以通过传递“受信任”的包(通常是与您的项目结构相关的包)来生成精简版的基线。这些包必须在单个参数中传递,用逗号(`,`)分隔 ``` $> aaw generate --archive=tmp/ProtonMail-3.0.7.apk --trusted='ch.protonmail,me.proton.core' Baseline available at : ch.protonmail.android.toml $> more ch.protonmail.android.toml applicationId = "ch.protonmail.android" permissions = [ "android.permission.ACCESS_NETWORK_STATE", "android.permission.FOREGROUND_SERVICE", "android.permission.GET_ACCOUNTS", "android.permission.INTERNET", "android.permission.READ_CONTACTS", "android.permission.READ_EXTERNAL_STORAGE", "android.permission.RECEIVE_BOOT_COMPLETED", "android.permission.SCHEDULE_EXACT_ALARM", "android.permission.USE_BIOMETRIC", "android.permission.USE_FINGERPRINT", "android.permission.VIBRATE", "android.permission.WAKE_LOCK", "android.permission.WRITE_EXTERNAL_STORAGE", "com.google.android.c2dm.permission.RECEIVE" ] features = [ "android.hardware.faketouch", "android.hardware.screen.portrait" ] trustedPackages = [ "ch.protonmail", "me.proton.core" ] activities = [ "androidx.biometric.DeviceCredentialHandlerActivity", "com.google.android.gms.common.api.GoogleApiActivity" ] . . . ``` ### 将归档文件与基线进行比较 ``` # 考虑前一个示例中生成的 baseline 文件 $> aaw compare -a tmp/ProtonMail-3.0.17.apk -b ch.protonmail.android.toml Your baseline file does not match the supplied artifact. ┌─────────────┬───────────────────────────────────────────────────────────────────┬────────────┐ │ Category │ Finding │ Missing at │ ├─────────────┼───────────────────────────────────────────────────────────────────┼────────────┤ │ Permissions │ android.permission.POST_NOTIFICATIONS │ Baseline │ ├─────────────┼───────────────────────────────────────────────────────────────────┼────────────┤ │ Permissions │ android.permission.READ_MEDIA_AUDIO │ Baseline │ ├─────────────┼───────────────────────────────────────────────────────────────────┼────────────┤ │ Permissions │ android.permission.READ_MEDIA_IMAGES │ Baseline │ ├─────────────┼───────────────────────────────────────────────────────────────────┼────────────┤ │ Permissions │ android.permission.READ_MEDIA_VIDEO │ Baseline │ ├─────────────┼───────────────────────────────────────────────────────────────────┼────────────┤ │ Components │ com.google.android.play.core.common.PlayCoreDialogWrapperActivity │ Baseline │ ├─────────────┼───────────────────────────────────────────────────────────────────┼────────────┤ │ Components │ androidx.profileinstaller.ProfileInstallReceiver │ Baseline │ └─────────────┴───────────────────────────────────────────────────────────────────┴────────────┘ ``` 此示例说明了如何作为 Continuous Integration(持续集成)的一部分来跟踪敏感变更,假设您在 CI 运行时生成了可发布归档文件的快照。 如果新生成的归档文件与现有基线不匹配,`compare` 也可以以失败状态退出,从而强制在 pull/merge request(合并请求)中更新基线。 ``` $> aaw compare -a tmp/ProtonMail-3.0.17.apk -b ch.protonmail.android.toml --fail ``` 此外,`compare` 也可以生成 `json` 格式的输出 ``` $> aaw compare -a tmp/ProtonMail-3.0.17.apk -b ch.protonmail.android.toml --json ``` ## 致谢 此工具的灵感来源于以下博客文章和现有工具 - [Android CI : Reveal Manifest changes in a Pull Request](https://proandroiddev.com/android-ci-reveal-manifest-changes-in-a-pull-request-a5cdd0600afa) - [How to compare apk / aab files](https://medium.com/bumble-tech/how-to-compare-apk-aab-files-par-1634563a5af6) - [Diffuse](https://github.com/JakeWharton/diffuse) ## 许可证 Copyright (c) 2025 - Dotanuki Labs - [The MIT license](https://choosealicense.com/licenses/mit/)
标签:AAB分析, AndroidSDK, Android开发, APK分析, DevSecOps, Java工具, Kotlin, Python安全, Shift-Left安全, 上游代理, 云安全监控, 依赖安全, 发布前检查, 开源框架, 持续集成, 文档结构分析, 权限监控, 目录枚举, 移动安全, 组件检测, 静态分析