Skip to content

fix(security): verify the iOS xcframeworks, and verify on every run rather than only a cold download - #2349

Merged
datlechin merged 1 commit into
mainfrom
fix/ios-libs-integrity
Aug 21, 2026
Merged

fix(security): verify the iOS xcframeworks, and verify on every run rather than only a cold download#2349
datlechin merged 1 commit into
mainfrom
fix/ios-libs-integrity

Conversation

@datlechin

Copy link
Copy Markdown
Member

The iOS xcframeworks were downloaded, extracted and linked with no integrity check of any kind, in CI included. 299 MB across 424 files, straight into a shipped app.

Two holes, not one

The iOS archive had no baseline at all. download-libs.sh verified the macOS .a files against Libs/checksums.sha256 committed in git, and did nothing whatsoever for Libs/ios.

The macOS check almost never ran either. The script opened with two exit 0 short-circuits: one on the .downloaded marker, one on finding any .a present. actions/cache restores Libs including the marker, so on a cache hit, which is what CI takes on nearly every run, the script returned before reaching the checksum step. The verification existed and was skipped.

What this does

Libs/ios/checksums.sha256 is now committed, covering all 424 regular files rather than just the library slices. The Info.plist inside an .xcframework is what selects which slice gets linked, so leaving it unhashed would leave a live tampering surface.

Libs/ios/ is gitignored, and git cannot re-include a file whose parent directory is excluded, so the pattern becomes Libs/ios/* plus a negation. Verified that only checksums.sha256 becomes trackable and git add Libs/ios/ still stages nothing else.

download-libs.sh is restructured so verification runs at the end, always, for both archives, whether or not anything was downloaded. The baselines are still read from HEAD before any extraction, for the reason the old comment already gave: each archive bundles its own checksums file, so verifying against the extracted copy is self-referential.

publish-ios-libs.sh is new, because a baseline nothing regenerates is a baseline that breaks everyone on the next rebuild. CLAUDE.md documented publishing as a bare tar czf … && gh release upload, which bypasses all of this; it now points at the script. The script reports what moved before publishing, refuses a publish where nothing changed, archives an allowlist rather than -C Libs/ios ., and tells you to commit the refreshed baseline.

Verified by exercising every path

cache-hit run, nothing downloaded both archives verified, exit 0
one Info.plist byte changed ERROR: Libs/ios does not match, exit 1
that file restored passes again
publisher, tree unchanged refuses: "Nothing to publish", exit 1
publisher, one file changed "1 changed, 0 added, 0 removed"

The baseline was also checked for stability: generating it twice produces identical bytes, and shasum -c verifies all 424 files against the tree.

One bug found by running it rather than reading it: the two baselines use different path conventions. Libs/checksums.sha256 holds Libs/… paths and must be checked from the repo root, while the iOS one holds ./… paths and must be checked from inside Libs/ios. The first version cd'd for both and failed every macOS library with "FAILED open or read".

A behaviour change worth calling out

Verification now runs against whatever is on disk, so rebuilding a library locally and then running anything that calls download-libs.sh fails rather than passing silently. That is the point, and the error names the two publish scripts. The alternative is what exists today: CI force-loading unverified static libraries into a signed, notarized binary because a cache hit skipped the check.

https://claude.ai/code/session_013MEaba8K1HQcyDNeq5wEFk

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@datlechin
datlechin merged commit 5496faf into main Aug 21, 2026
7 checks passed
@datlechin
datlechin deleted the fix/ios-libs-integrity branch August 21, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant