verifyOS-cli
verifyOS-cli is a pure Rust, cross-platform CLI tool designed to scan Apple app bundles (like .ipa, .app, Info.plist, and Mach-O binaries) for App Store rejection risks before submission. Operating locally or within an automated CI pipeline, it catches potential App Store Connect rejections left of the build process.
The App Store Connect validation step is historically a "black box" that costs developers hours of waiting. By shifting validation to your local machine—or a fast, cheap Linux runner—verifyOS-cli empowers solo developers and robust teams alike. 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.
- 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
Quick start
Run the CLI tool against your .ipa or .app path:
Output Formats
Table (default):
JSON:
SARIF (for GitHub code scanning, etc.):
Markdown report (agent-friendly):
Baseline Mode
Suppress existing findings by providing a baseline JSON report. Only new failing findings will be shown:
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 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ 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 │
╰────────────────────────────────────────┴─────────────┴──────────┴────────┴────────────────────────────────────────────────────────────╯
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: lint + tests on push and pull request.
- Automated release PRs:
release-plzworkflow. - Publishing: crates.io + GitHub release artifacts.
License
MIT