14 releases
| new 0.3.1 | Mar 12, 2026 |
|---|---|
| 0.3.0 | Mar 12, 2026 |
| 0.2.3 | Mar 12, 2026 |
| 0.1.7 | Mar 11, 2026 |
#5 in #app-store
160KB
4K
SLoC
Contains (Zip file, 2KB) examples/good_app.ipa, (Zip file, 1KB) examples/bad_app.ipa
verifyOS-cli is an AI agent-friendly, pure Rust CLI for scanning Apple app bundles (like .ipa, .app, Info.plist, and Mach-O binaries) for App Store rejection risks before submission. It is built for developers, vibecoders, and automation workflows that want fast, local feedback before App Store Connect becomes the bottleneck.
The App Store Connect validation step is historically a "black box" that costs developers hours of waiting. By shifting validation to your local machine, CI runner, or AI agent loop, verifyOS-cli helps teams catch rejection risks early and produce structured output an agent can use to patch issues faster. Unlike Apple's toolchain (codesign, otool), this tool is built entirely in Rust.
What it does
- Acts as a local static analysis orchestrator for iOS/macOS apps.
- Ruleset metadata: Every finding includes
rule_id,severity, andcategory(Privacy, Entitlements, Metadata, etc.). - Privacy Manifests: Checks for missing
PrivacyInfo.xcprivacy. - Permissions (Info.plist): Uses a heuristic Mach-O scan to infer which
NS*UsageDescriptionkeys are required, then validates presence and non-empty values. - LSApplicationQueriesSchemes: Audits custom URL scheme allowlists for duplicates, invalid entries, and potential private schemes.
- UIRequiredDeviceCapabilities: Flags capabilities that don't match observed binary usage.
- ATS: Flags overly broad ATS exceptions (global allows, includes subdomains, insecure TLS settings).
- Bundle leakage: Fails if sensitive files (e.g.,
.p12,.pem,.mobileprovision,.env) are found inside the app bundle. - Versioning: Ensures
CFBundleShortVersionStringandCFBundleVersionare valid and present. - Extension entitlements: Validates extension entitlements are a subset of the host app and required keys exist for common extension types.
- Privacy SDK cross-check: Warns if common SDK signatures are detected but PrivacyInfo.xcprivacy lacks declarations.
- Entitlements: Detects debug-only entitlements (like
get-task-allow=true) and flags mismatches between app entitlements andembedded.mobileprovision(APNs, keychain groups, iCloud containers). - Signing: Ensures embedded frameworks/extensions are signed with the same Team ID as the app binary.
- CI-friendly reports: Outputs
table,json, orsarifwith evidence and remediation recommendations.
Installation
From crates.io
cargo install verifyos-cli
This installs the voc binary for the CLI.
Quick start
Run the CLI tool against your .ipa or .app path:
voc --app path/to/YourApp.ipa
Profiles
Run a smaller core ruleset or the full scan:
voc --app path/to/YourApp.ipa --profile basic
voc --app path/to/YourApp.ipa --profile full
full is the default if --profile is omitted.
Exit thresholds
Control when the CLI exits with code 1:
voc --app path/to/YourApp.ipa --fail-on off
voc --app path/to/YourApp.ipa --fail-on warning
error is the default if --fail-on is omitted.
Rule selectors
Run only specific rules or exclude noisy ones by rule ID:
voc --app path/to/YourApp.ipa --include RULE_PRIVATE_API,RULE_ATS_AUDIT
voc --app path/to/YourApp.ipa --exclude RULE_PRIVATE_API
Selectors apply after the chosen --profile, so basic plus --include can narrow the set even further.
Rule inventory
List available rules and their default profile membership:
voc --list-rules
Machine-readable inventory for agents and CI:
voc --list-rules --format json
Config file
If verifyos.toml exists in the current working directory, voc will load it automatically. You can also point to a specific config file:
voc --app path/to/YourApp.ipa --config verifyos.toml
Example config:
format = "table"
profile = "full"
fail_on = "error"
timings = "off"
include = []
exclude = []
CLI flags override config file values.
Output Formats
Table (default):
voc --app path/to/YourApp.ipa --format table
JSON:
voc --app path/to/YourApp.ipa --format json > report.json
SARIF (for GitHub code scanning, etc.):
voc --app path/to/YourApp.ipa --format sarif > report.sarif
Markdown report (agent-friendly):
voc --app path/to/YourApp.ipa --md-out report.md
Timing summary:
voc --app path/to/YourApp.ipa --timings
Full timing details:
voc --app path/to/YourApp.ipa --timings full
--timings by itself defaults to summary, which prints total scan time, slowest rules, and cache activity without adding a per-rule time column. Use --timings full when you want the table and markdown outputs to include per-rule execution times too.
JSON and Markdown reports still carry timing data for automation and profiling.
The timing summary also highlights the slowest rules so you can spot hot paths quickly.
It also includes cache hit/miss activity for artifact scans so we can tell whether a slow run is coming from repeated IO or genuinely expensive rules.
JSON and SARIF outputs now expose machine-readable perf metadata too, including slow_rules, total_duration_ms, and cache telemetry.
Baseline Mode
Suppress existing findings by providing a baseline JSON report. Only new failing findings will be shown:
voc --app path/to/YourApp.ipa --format json > baseline.json
voc --app path/to/YourApp.ipa --baseline baseline.json
Baseline matching currently uses rule_id + evidence for failing findings.
Example Passing Output
Analysis complete!
╭────────────────────────────────────────┬─────────────┬──────────┬────────┬─────────╮
│ Rule ┆ Category ┆ Severity ┆ Status ┆ Message │
╞════════════════════════════════════════╪═════════════╪══════════╪════════╪═════════╡
│ Missing Privacy Manifest ┆ Privacy ┆ ERROR ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Missing Camera Usage Description ┆ Permissions ┆ ERROR ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ LSApplicationQueriesSchemes Audit ┆ Metadata ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ UIRequiredDeviceCapabilities Audit ┆ Metadata ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ ATS Exceptions Too Broad ┆ ATS ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Sensitive Files in Bundle ┆ Bundling ┆ ERROR ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Info.plist Versioning Consistency ┆ Metadata ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Extension Entitlements Compatibility ┆ Entitlements┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Privacy Manifest vs SDK Usage ┆ Privacy ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ Debug Entitlements Present ┆ Entitlements┆ ERROR ┆ PASS ┆ PASS │
╰────────────────────────────────────────┴─────────────┴──────────┴────────┴─────────╯
Example Failing Output (Exits with code 1)
Analysis complete!
╭────────────────────────────────────────┬─────────────┬──────────┬────────┬────────────────────────────────────────────────────────────╮
│ Rule ┆ Category ┆ Severity ┆ Status ┆ Message │
╞════════════════════════════════════════╪═════════════╪══════════╪════════╪════════════════════════════════════════════════════════════╡
│ Missing Privacy Manifest ┆ Privacy ┆ ERROR ┆ FAIL ┆ Missing PrivacyInfo.xcprivacy │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Missing required usage description keys┆ Privacy ┆ WARNING ┆ FAIL ┆ Missing required usage description keys │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ LSApplicationQueriesSchemes Audit ┆ Metadata ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ UIRequiredDeviceCapabilities Audit ┆ Metadata ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ ATS Exceptions Too Broad ┆ ATS ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Sensitive Files in Bundle ┆ Bundling ┆ ERROR ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Info.plist Versioning Consistency ┆ Metadata ┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Extension Entitlements Compatibility ┆ Entitlements┆ WARNING ┆ PASS ┆ PASS │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ Privacy Manifest vs SDK Usage ┆ Privacy ┆ WARNING ┆ PASS ┆ PASS │
╰────────────────────────────────────────┴─────────────┴──────────┴────────┴────────────────────────────────────────────────────────────╯
Architecture
This project is structured with modularity in mind:
core/: Orchestrator and logic execution engine.parsers/: Format handlers (zipextraction,plistmapping,goblin/apple-codesignMach-O inspection).rules/: Trait-based rule engine representing the validation checks.
Conventional Commits
To ensure the automated semantic versioning and changelog parsing through the release-plz bot behaves properly, developers MUST use Git Conventional Commits format:
feat:A new feature (correlates to a MINORv0.X.0bump).fix:A bug fix (correlates to a PATCHv0.0.Xbump).docs:Documentation only changes.chore:Changes to the build process or auxiliary tools.
CI and releases
- CI: fmt + clippy + tests on push and pull request.
- Automated release PRs:
release-plzworkflow. - Publishing: crates.io + GitHub release artifacts.
License
MIT
Dependencies
~55–80MB
~1.5M SLoC