Skip to content

Give the frozen exporter a CA bundle when the system offers none - #209

Merged
parawanderer merged 1 commit into
mainfrom
fix/exporter-linux-ssl
Sep 14, 2026
Merged

parawanderer merged 1 commit into
mainfrom
fix/exporter-linux-ssl

Conversation

@parawanderer

Copy link
Copy Markdown
Owner

Fixes the Linux SSL failure in #206: sign-in works, then the mobileme login at setup.icloud.com right after the 2FA code fails with CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate.

Why only that one host

Every Apple request is TLS-verified by FindMy.py against the platform's trust store plus Apple's own pinned 2006 root, which the library carries.

  • gsa.apple.com (sign-in) chains to that pinned root, so it verifies with no system trust store at all.
  • setup.icloud.com (the mobileme login) presents an ordinary public certificate — issued by Apple Public Server ECC CA 1 - G1 — that needs the platform's CA bundle like any website.

A PyInstaller build carries no trust store, and its Python looks for one at the paths OpenSSL was compiled with on the build machine, which do not exist on the user's. So sign-in succeeded against the pinned root and the very next request died. The reporter confirmed export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt fixed it.

The fix

exporter.certs.ensure_ca_bundle() does that workaround portably: it points SSL_CERT_FILE at certifi's bundled certificates (already a dependency), which ssl.create_default_context() reads when FindMy.py builds its context. Both entry points (cli.main, wizard.__main__) call it before the first request.

It only fills a gap — it leaves a user's own SSL_CERT_FILE and a machine with a working default bundle untouched — so from-source runs are unaffected.

Verification

  • certifi's bundle verifies setup.icloud.com from this machine (the failing host).
  • python/test/test_certs.py, 4 tests: respects an existing SSL_CERT_FILE, leaves a working system store alone, fills the gap from certifi when the default is missing, and sets nothing when certifi is absent.
  • Full exporter suite: 474 passed, 2 skipped. flake8 and pyright clean.

Not touched: the app (Chaquopy on Android has a working system store — the app's failure in that thread is a 429, a separate problem).

🤖 Generated with Claude Code

Sign-in succeeded and then the very next request, the mobileme login at
setup.icloud.com, died with CERTIFICATE_VERIFY_FAILED on a minimal Linux desktop
(#206). gsa.apple.com chains to the Apple root FindMy.py pins and carries, so it
verifies with no trust store; setup.icloud.com presents an ordinary public
certificate that needs the platform's CA bundle, and a PyInstaller build has none
- its Python looks for one at the build machine's paths, absent on the user's.

exporter.certs.ensure_ca_bundle points OpenSSL at certifi's bundled certificates
through SSL_CERT_FILE, which is what the reporter set by hand as the workaround,
and which ssl.create_default_context reads when FindMy.py builds its context. Both
entry points call it before the first request.

It only fills a gap: a user's own SSL_CERT_FILE and a machine whose default bundle
exists are both left untouched, so from-source runs are unaffected.

Closes #206.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@parawanderer parawanderer added bug Something isn't working @exporter-tool Issues regarding the desktop export tool (wizard and CLI) labels Sep 14, 2026
@parawanderer
parawanderer merged commit 91ff00a into main Sep 14, 2026
6 checks passed
@parawanderer parawanderer mentioned this pull request Sep 14, 2026
1 task done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working @exporter-tool Issues regarding the desktop export tool (wizard and CLI)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant