Skip to content

security: migrate iOS secrets from UserDefaults to Keychain - #74

Open
juliosuas wants to merge 2 commits into
Intent-Lab:mainfrom
juliosuas:fix/security-warnings-and-keychain
Open

security: migrate iOS secrets from UserDefaults to Keychain#74
juliosuas wants to merge 2 commits into
Intent-Lab:mainfrom
juliosuas:fix/security-warnings-and-keychain

Conversation

@juliosuas

Copy link
Copy Markdown

Problem

API keys and tokens (Gemini API key, OpenClaw gateway token, hook token) are stored in UserDefaults, which is:

  • Unencrypted on disk
  • Readable from device backups (iTunes/Finder)
  • Accessible to other apps on jailbroken devices

This was flagged in Issue #1 (API key leaking) and is also relevant to PR #8 (in-app secrets management).

Fix

New: KeychainManager.swift

Thin wrapper around Security.framework — 59 lines, zero dependencies:

  • get(_:) / set(_:value:) / delete(_:) / deleteAll()
  • Uses kSecClassGenericPassword with a service identifier
  • Update-first strategy (cheaper than delete+add)

Changed: SettingsManager.swift

  • Secrets (API keys, tokens) → Keychain (encrypted, hardware-backed)
  • Settings (host, port, toggles) → UserDefaults (unchanged, non-sensitive)
  • Auto-migration: on first launch after update, moves existing UserDefaults secrets to Keychain and deletes the old entries

Migration Behavior

Existing user What happens
Has secrets in UserDefaults Auto-migrated to Keychain on first launch, then deleted from UserDefaults
New install Secrets go directly to Keychain
Reset all settings Both Keychain and UserDefaults are cleared

Files Changed

  • Settings/KeychainManager.swift (new)
  • Settings/SettingsManager.swift (modified)

Test plan

  • Fresh install: enter API key in Settings → verify it persists across app restarts
  • Existing install: verify secrets auto-migrate (check "Migrated ... to Keychain" in logs)
  • Reset all settings → verify API key is cleared
  • Verify UserDefaults plist no longer contains API keys (inspect with plutil)

🤖 Generated with Claude Code


Restored after an accidental fork deletion. Same commits as #41.

julscezar and others added 2 commits April 6, 2026 05:06
…tent-Lab#1)

API keys and tokens were stored in UserDefaults, which is unencrypted
and readable from device backups. This is a security risk flagged in
Issue Intent-Lab#1.

Changes:
- New KeychainManager.swift: thin wrapper around Security.framework
  for storing/retrieving sensitive strings in the iOS Keychain
- SettingsManager now stores geminiAPIKey, openClawHookToken, and
  openClawGatewayToken in Keychain instead of UserDefaults
- One-time automatic migration: existing UserDefaults secrets are
  moved to Keychain on first launch, then deleted from UserDefaults
- Non-sensitive settings (host, port, toggles) remain in UserDefaults

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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