Apple public repo security
Skill wei18/apple-dev-skills/apple-dev-skills/skills/apple-public-repo-security
Reusable Claude Code skills for AI-agent-driven Swift / Apple-platform development — composable via git submodule; aggregates other specialist skill repos
npx -y skills add wei18/apple-dev-skills --skill apple-public-repo-securityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Security baseline for public iOS / macOS repos — secret classification (CloudKit PEM, ASC API key, APNs key, signing cert, provisioning profiles), `.gitignore` baseline, three lines of defence (mise gitleaks + lefthook pre-commit · Xcode Cloud `ci_post_clone.sh` · GitHub Secret Scanning), rotate-first leak SOP (`git filter-repo`, fork persistence), Apple upstream telemetry disclosure (MetricKit / Game Center / sysdiagnose). Invoke when a repo goes public, an existing repo open-sources, a secret enters the build pipeline, or asked "how to prevent secret leaks in a public repo". Repo-hygiene baseline; for ship-in-binary identifiers (AdMob ID via xcconfig `$()`) see build-time-secret-injection.
SKILL.md
8.1 KB, as published. Nobody here has run it
Apple Public Repo Security
When to invoke
- The repo will be public from day 1.
- An existing private repo is planning to open-source.
- A new secret is being introduced (CloudKit server-to-server key, APNs key, ASC API key).
- User asks "how do I prevent secret leaks in a public repo", "how do I configure Xcode Cloud secrets", "what to do after a leak".
Default decisions
Public commitment from day 1
- No "private first, public later" transition — there's no escape hatch to "clean history later".
- No commit in the repo's history may contain secret values, PII, or identifiable player data.
- A violation, once it happens, is treated as already leaked and the secret is rotated.
Secret classification
| Secret | Purpose | Storage |
|---|---|---|
| CloudKit server-to-server key (Key ID + PEM) | Backend API | Xcode Cloud Env Vars (Secret); locally in ~/.config/<project>/ (chmod 600) or Keychain |
App Store Connect API Key (.p8 + Key ID + Issuer ID) | TestFlight / submission automation | Xcode Cloud Env Vars (Secret) |
APNs Auth Key (.p8 + Key ID + Team ID) | Push notifications | Xcode Cloud Env Vars (Secret) |
Signing certificate + private key (.p12) | Code signing | Xcode Cloud automatic signing, hosted by Apple |
| Provisioning profiles | Code signing | Xcode Cloud Apple-managed |
| Player identification data | Runtime debug | OSLog .private interpolation; never committed to git |
Things that must not enter git
- The actual content of the secrets above (including base64-encoded forms)
- Real player aliases / displayNames / playerIDs (except after hashing)
- Apple Developer Team ID / DUNS / address (if they appear in entitlements / profile metadata)
- Build logs containing secrets (redact before viewing)
- Developers' local
.config/<project>/real files - Personal notes / drafts (like
NOTES.md.private)
Starter .gitignore
# Secrets / credentials
*.pem
*.p8
*.p12
*.mobileprovision
*.cer
.env
.env.*
!.env.example
secrets/
# Xcode / build
DerivedData/
build/
xcuserdata/
*.xcuserstate
.swiftpm/
# macOS
.DS_Store
# Personal notes
*.private.md
NOTES.md.private
# Local development secrets directory (chmod 600 PEMs / API keys live here)
.config/
!.config/example/ # If a public example directory exists, allow listing it
Three lines of defence
| Line | Tool | Scope |
|---|---|---|
| 1. Local pre-commit | lefthook + gitleaks (via mise) | Catches staged diffs; can be bypassed with --no-verify |
| 2. CI post-clone | Xcode Cloud ci_post_clone.sh runs gitleaks | Catches at PR time; fails the build; earliest stage is cheapest |
| 3. GitHub Secret Scanning Alerts | GitHub platform (free on public repos) | Passive detection; Apple-issued secret patterns auto-revoke via partner program |
lefthook.yml example:
pre-commit:
parallel: true
commands:
gitleaks:
run: mise exec gitleaks -- git --pre-commit --staged --redact --verbose
ci_post_clone.sh example:
mise install
mise exec gitleaks -- git --pre-commit --staged --redact
if [ $? -ne 0 ]; then
echo "gitleaks detected potential secrets — failing build"
exit 1
fi
Leak SOP (rotate before cleaning history)
- Rotate first (rotation is the real stop-bleed; after a force push, GitHub reflog / forks may still reach the secret for up to 90 days, and any fork retains it forever):
- CloudKit Dashboard: rotate the server-to-server key
- Rotate the ASC API key
- Rotate the APNs key
- Signing cert leak: revoke + reissue in Apple Developer Center
- Use
git filter-repoto clean history + force push (git filter-branchis deprecated, do not use) - Notify GitHub support to purge forks / caches — acknowledge that fork removal is not guaranteed
- Open an incident log + lessons learned under
meetings/ - Do not continue other development until the four steps above are done
Setup templates (shipped in the repo)
.env.example: list all env var keys with placeholder values.config/<project>/example/README.md: explain the local PEM directory layout (do not include a.pem.examplereal file — gitleaks's built-inprivate-keyrule fires on the header alone; if you must include a real example, explicitly allowlist it in.gitleaks.toml)docs/setup.md: first-clone steps for new developers
Public commitment on Apple upstream channels
The App's commitment to users (aligned with PrivacyInfo.xcprivacy):
- No PII collection
- No third-party tracking SDK
- The App does not upload events to "our" servers (CloudKit / Game Center are provided by Apple)
Legitimate Apple upstream channels (users can disable in Settings):
- MetricKit
MXMetricPayload→ ASC Power & Performance (Settings → Privacy → Analytics & Improvements) - Game Center scores / achievements (Settings → Game Center)
- ASC crash reports / TestFlight beta crashes (when the user enables Share Analytics)
- sysdiagnose (when the user actively shares via Feedback Assistant; OSLog
.privateis redacted here)
Extra responsibilities for code reviewers
Every PR review additionally checks:
- No new secret pattern slipped through
- No secret values mentioned in docs / comments / commit messages / PR descriptions
- No identifiable info in screenshots / assets
- If privacy claims change →
PrivacyInfo.xcprivacy+ App Store metadata are updated in sync - Any "temporarily log PII for debug" helper is removed before merging
Rationale
- Three lines of defence are standard defence-in-depth, with complementary interception stages.
- The rotate-first SOP reflects the reality that "git history is permanently reachable in forks" — cleaning history is not stopping the bleed.
- Apple-issued secrets go through GitHub's partner program for auto-revocation; the third line is a free, must-enable layer.
Deviation considerations
- Private repo planning to go public later: start with this skill, but allow some templates (e.g.
.pem.example) to hold real files temporarily; clean up before going public. - No CI (pure local development): the first line of defence (local pre-commit hook) can be bypassed by
git commit --no-verify— this cannot be technically blocked client-side. Educate contributors, and rely on the second line (CI gitleaks inci_post_clone.sh) as the actual hard gate. Without CI, the second line is missing entirely; mitigations are social (code review, contributor education) rather than technical. - Internal corporate repo: the third line (GitHub platform) can be skipped, but the first and second still apply.
Verification checklist
.gitignorecovers the secret file extensions listed above..mise.tomlincludes gitleaks + lefthook.lefthook.ymlruns gitleaks pre-commit.ci_post_clone.shruns gitleaks with fail-on-detect.- GitHub Settings → Code security → Secret scanning alerts is enabled.
docs/setup.mdinstructslefthook installto activate hooks.PrivacyInfo.xcprivacyis consistent with the public commitments.
Related skills
mise-tool-management: gitleaks + lefthook installed via mise.xcode-cloud-single-track-ci:ci_post_clone.shis where the second line lives.oslog-logger-defaults:.privateinterpolation matches the sysdiagnose redaction semantics.apple-three-piece-analytics: "no third-party SDK" is one of the public commitments.