dotanuki-labs/android-archives-watchdog
GitHub: dotanuki-labs/android-archives-watchdog
一款专注Android发布包安全左移的CLI工具,通过基线对比机制检测Manifest中权限和组件的敏感变更。
Stars: 14 | Forks: 0
# Android Archives Watchdog 🐶
[](https://ktlint.github.io/)
[](https://github.com/dotanuki-labs/android-archives-watchdog/actions/workflows/ci.yaml)
[](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安全, 上游代理, 云安全监控, 依赖安全, 发布前检查, 开源框架, 持续集成, 文档结构分析, 权限监控, 目录枚举, 移动安全, 组件检测, 静态分析