Permission Guard Pro
The permission-guard command extracts permissions from compiled artifacts — APK via apkanalyzer and IPA via plist parsing — then diffs them against a committed baseline. This catches permissions injected by third-party libraries at compile time, which source-level AndroidManifest.xml diffing cannot detect.
Why compiled extraction matters
A library added to pubspec.yaml can inject permissions into the merged AndroidManifest.xml during the Gradle build without any change to your source manifests. permission-guard reads permissions from the final artifact so no injection goes unnoticed.
Prerequisites
| Tool | Required for | How to install |
|---|---|---|
apkanalyzer | Android | Android SDK command-line tools (cmdline-tools/latest/bin/) |
unzip | iOS | Pre-installed on macOS and standard Linux distributions |
Commands
android
dart run monorepo_toolkit permission-guard android \
--apk build/app/outputs/flutter-apk/app-release.apk
# Diff against a baseline
dart run monorepo_toolkit permission-guard android \
--apk build/app/outputs/flutter-apk/app-release.apk \
--baseline permission_baseline/android.txtios
dart run monorepo_toolkit permission-guard ios \
--ipa build/ios/ipa/MyApp.ipa
# Diff against a baseline
dart run monorepo_toolkit permission-guard ios \
--ipa build/ios/ipa/MyApp.ipa \
--baseline permission_baseline/ios.txtupdate-baseline
dart run monorepo_toolkit permission-guard update-baseline \
--platform android \
--artifact build/app/outputs/flutter-apk/app-release.apk \
--output permission_baseline/android.txtFlags
| Flag | Commands | Default | Description |
|---|---|---|---|
--apk | android | required | Path to the compiled APK |
--ipa | ios | required | Path to the compiled IPA |
--baseline | android, ios | none | Path to committed baseline file to diff against |
--platform | update-baseline | required | android or ios |
--artifact | update-baseline | required | Path to APK or IPA for baseline extraction |
--output | update-baseline | required | Destination path for the new baseline file |
Baseline pattern
Baselines are committed to the repository at:
permission_baseline/
├── android.txt
└── ios.txtUpdate baselines after a deliberate permission change by running update-baseline and committing the result.
Configuration
Create a .permissionguard.yaml at the workspace root to control failure behavior:
permission_guard:
fail_on_new: true
warn_on_removed: true| Key | Default | Description |
|---|---|---|
fail_on_new | true | Exit 1 if new permissions are detected |
warn_on_removed | true | Print a warning (but do not fail) if permissions were removed |
CI integration
# Android permission gate on PR
- name: Permission guard (Android)
run: |
dart run monorepo_toolkit permission-guard android \
--apk build/app/outputs/flutter-apk/app-release.apk \
--baseline permission_baseline/android.txt
# iOS permission gate on PR
- name: Permission guard (iOS)
run: |
dart run monorepo_toolkit permission-guard ios \
--ipa build/ios/ipa/MyApp.ipa \
--baseline permission_baseline/ios.txt
# Update baseline on develop merge (Android example)
- name: Update permission baseline
if: github.ref == 'refs/heads/develop'
run: |
dart run monorepo_toolkit permission-guard update-baseline \
--platform android \
--artifact build/app/outputs/flutter-apk/app-release.apk \
--output permission_baseline/android.txt
git add permission_baseline/android.txt
git commit -m "chore: update android permission baseline"
git push