swift-security-expert
iOS/macOS の Keychain Services(SecItem クエリ・kSecClass・OSStatus エラー)、生体認証(LAContext・Face ID・Touch ID)、CryptoKit(AES-GCM・ChaChaPoly・ECDSA・ECDH・HPKE・ML-KEM)、Secure Enclave、セキュアな認証情報の保存(OAuth トークン・API キー)、証明書ピニング(SecTrust・SPKI)、アプリ/拡張機能間の Keychain 共有、UserDefaults や plist からの秘密情報移行、あるいは Apple プラットフォームにおける OWASP MASVS/MASTG モバイルコンプライアンス対応を行う際に使用します。
description の原文を見る
Use when working with iOS/macOS Keychain Services (SecItem queries, kSecClass, OSStatus errors), biometric authentication (LAContext, Face ID, Touch ID), CryptoKit (AES-GCM, ChaChaPoly, ECDSA, ECDH, HPKE, ML-KEM), Secure Enclave, secure credential storage (OAuth tokens, API keys), certificate pinning (SecTrust, SPKI), keychain sharing across apps/extensions, migrating secrets from UserDefaults or plists, or OWASP MASVS/MASTG mobile compliance on Apple platforms.
SKILL.md 本文
Keychain & Security Expert Skill
哲学: 無党派的でありながら正確性重視。このスキルは事実、検証済みのパターン、Apple公式ドキュメントによるベストプラクティスを提供します。建築上の指示ではありません。iOS 13以上を最小デプロイターゲットとしてカバーし、iOS 17以上を対象とした最新の推奨事項と、iOS 26(ポスト量子)を通じた前向きなガイダンスを提供します。すべてのコードパターンはAppleドキュメント、DTS エンジニアポスト (Quinn "The Eskimo!")、WWDCセッション、OWASP MASTGに基づいており、記憶だけでは生成されません。
このスキルが対象とすること: Appleプラットフォーム上のキーチェーン操作、生体認証、CryptoKitの暗号化、認証情報ライフサイクル管理、証明書信頼、コンプライアンスマッピングのレビュー、改善、実装のためのリファレンスです。
このスキルが対象外のこと: ネットワーキングガイド、サーバー側のセキュリティリファレンス、App Transport Securityマニュアルではありません。TLS設定、サーバー証明書管理、バックエンド認証アーキテクチャは、クライアント側のキーチェーンまたは信頼APIに直接関わる場合を除き対象外です。
Decision Tree
ユーザーの意図を特定し、対応するブランチに従います。曖昧な場合は確認してください。
┌─────────────────────┐
│ タスクは何か? │
└─────────┬───────────┘
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌─────────┐ ┌───────────┐ ┌────────────┐
│ レビュー │ │ 改善 │ │ 実装 │
│ │ │ │ │ │
│ 既存 │ │ 移行 / │ │ ゼロから │
│ コード │ │ 最新化 │ │ 構築 │
│ の監査 │ │ 既存コード│ │ │
└────┬────┘ └─────┬─────┘ └─────┬──────┘
│ │ │
▼ ▼ ▼
トップレベル ギャップ識別 対象ドメイン
レビュー (レガシーストア? の識別、
チェックリスト 間違ったAPI? リファレンス
をコードに対して 認証なし?) ファイルの
実行 移行+ドメイン ロード、✅
各項目を 特定のリファレンス パターンに従う
✅ / ❌ / ファイル読み込み 追加またはアップデート
⚠️ N/Aとしてマーク 正しいパターンに で実装、
各❌について 従う、ドメイン 適切なエラー処理
リファレンス チェックリストで と正確なアクセス
ファイルとその 確認 制御から開始
セクションを
引用
ブランチ 1 — レビュー (既存コードの監査)
目標: 既存のキーチェーン/セキュリティコードを体系的に評価して、正確性、セキュリティ、コンプライアンスを検証します。
手順:
- トップレベルレビューチェックリスト (下記)をレビュー対象のコードに対して実行します。各項目を ✅ / ❌ / ⚠️ N/A でスコアリングします。
- 各❌の失敗について、 引用されたリファレンスファイルをロードし、特定のアンチパターンまたは正しいパターンを探します。
- アンチパターンをクロスチェック —
common-anti-patterns.mdの10個すべてに対してコードをスキャンします。特に以下に注意してください:UserDefaultsでのシークレット (#1)、ハードコードされたキー (#2)、LAContext.evaluatePolicy()が唯一の認証ゲート (#3)、無視されたOSStatus(#4)。 - コンプライアンスを確認 — プロジェクトがOWASP MAVSまたはエンタープライズ監査対応が必要な場合、
compliance-owasp-mapping.mdのカテゴリ M1、M3、M9、M10 に検出を対応付けます。 - 報告形式: 各検出について、以下を記述します: 何が悪いのか → どのリファレンスファイルがそれをカバーするのか → ✅正しいパターン → 重要度 (CRITICAL / HIGH / MEDIUM)。
レビューの重要なリファレンスファイル:
- 開始:
common-anti-patterns.md(バックボーン — 最も危険な10パターンをカバー) - その後、コードが実行することに基づいてドメイン特定ファイル
- 完了:
compliance-owasp-mapping.md(コンプライアンスが関連する場合)
ブランチ 2 — 改善 (移行 / 最新化)
目標: 既存コードを安全でないストレージ、非推奨API、またはレガシーパターンから最新のベストプラクティスにアップグレードします。
手順:
-
移行タイプを特定:
- 安全でないストレージ → キーチェーン:
migration-legacy-stores.md+credential-storage-patterns.mdをロード - レガシーSecurity framework → CryptoKit:
cryptokit-symmetric.mdまたはcryptokit-public-key.md+migration-legacy-stores.mdをロード - RSA → 楕円曲線:
cryptokit-public-key.md(RSA移行セクション) をロード - GenericPassword → InternetPassword (AutoFill):
keychain-item-classes.md(移行セクション) をロード - LAContext のみ → キーチェーン連携生体認証:
biometric-authentication.mdをロード - ファイルベースキーチェーン → データ保護キーチェーン (macOS):
keychain-fundamentals.md(TN3137セクション) をロード - 単一アプリ → 共有キーチェーン (拡張機能):
keychain-sharing.mdをロード - リーフピン留め → SPKI/CAピン留め:
certificate-trust.mdをロード
- 安全でないストレージ → キーチェーン:
-
関連するリファレンスファイルの移行パターンに従います。 すべての移行セクションには、以下が含まれます: 移行前の検証、アトミック移行ステップ、レガシーデータの安全な削除、移行後の検証。
-
移行完了後、リファレンスファイルのドメイン特定チェックリストを実行します。
-
testing-security-code.mdのガイダンスを使用して回帰がないか検証します。
ブランチ 3 — 実装 (ゼロから構築)
目標: 新しいキーチェーン/セキュリティ機能を最初から正しく構築します。
手順:
- タスクが対象とするドメインを特定します。 下記の「ドメイン選択ガイド」を使用してください。
- 関連するリファレンスファイルをロードします。 ✅コードパターンに従う — コアセキュリティロジックに関しては決してそれらから逸脱しないでください。
- すべての実装に対して「コアガイドライン」 (下記) を適用します。
- 実装が完了したと考える前に、ドメイン特定チェックリストを実行します。
testing-security-code.mdに従ってテストを追加します — ユニットテスト用のプロトコルベースの抽象化、デバイス上の統合テスト用の実際のキーチェーン。
ドメイン選択ガイド:
| タスクが関わる場合… | これらのリファレンスファイルをロード |
|---|---|
| パスワードまたはトークンの保存/読み取り | keychain-fundamentals.md + credential-storage-patterns.md |
どの kSecClass を使用するか選択 | keychain-item-classes.md |
| アイテムがアクセス可能な時期を設定 | keychain-access-control.md |
| Face ID / Touch ID ゲート | biometric-authentication.md + keychain-access-control.md |
| ハードウェアバック キー | secure-enclave.md |
| データの暗号化 / ハッシング | cryptokit-symmetric.md |
| 署名 / 鍵交換 / HPKE | cryptokit-public-key.md |
| OAuthトークン / APIキー / ログアウト | credential-storage-patterns.md |
| アプリと拡張機能の共有 | keychain-sharing.md |
| TLSピン留め / クライアント証明書 | certificate-trust.md |
| UserDefaults / plist シークレットの置き換え | migration-legacy-stores.md |
| セキュリティコードのテスト作成 | testing-security-code.md |
| エンタープライズ監査 / OWASPコンプライアンス | compliance-owasp-mapping.md |
コアガイドライン
これら7つのルールは交渉の余地がありません。すべてのキーチェーン/セキュリティ実装はこれらすべてを満たす必要があります。
1. OSStatus を決して無視しないでください。 すべての SecItem* 呼び出しは OSStatus を返します。最低でも以下をカバーする網羅的な switch を使用してください: errSecSuccess、errSecDuplicateItem (-25299)、errSecItemNotFound (-25300)、errSecInteractionNotAllowed (-25308)。戻り値を無視することは、ほとんどのキーチェーンバグの根本原因です。→ keychain-fundamentals.md
2. LAContext.evaluatePolicy() をスタンドアロン認証ゲートとして決して使用しないでください。 これは Bool を返しますが、Fridaを使用した実行時パッチでは些細な問題です。生体認証は、キーチェーン連携である必要があります: SecAccessControl と .biometryCurrentSet を使用してシークレットを保存し、SecItemCopyMatching 中にキーチェーンにFace ID/Touch IDの入力をさせてください。キーチェーンはSecure Enclaveで認証を処理します — パッチするための Bool は存在しません。→ biometric-authentication.md
3. UserDefaults、Info.plist、.xcconfig、または NSCoding アーカイブにシークレットを決して保存しないでください。 これらは暗号化されていないバックアップから読み取り可能なプレーンテキストアーティファクトを生成します。キーチェーンは認証情報用に唯一のApple公認ストアです。→ credential-storage-patterns.md、common-anti-patterns.md
4. SecItem* を @MainActor で決して呼び出さないでください。 すべてのキーチェーン呼び出しは securityd へのIPC ラウンドトリップで呼び出しスレッドをブロックします。iOS 17+ の専用 actor または iOS 13–16 のシリアル DispatchQueue を使用してすべてのキーチェーンアクセスを実行してください。→ keychain-fundamentals.md
5. 常に kSecAttrAccessible を明示的に設定してください。 システムの既定値 (kSecAttrAccessibleWhenUnlocked) はすべてのバックグラウンド操作を破壊し、脅威モデルと合致しない可能性があります。アクセスパターンを満たす最も制限的なクラスを選択してください。バックグラウンドタスク用: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly。最高感度用: kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly。→ keychain-access-control.md
6. 常に追加または更新パターンを使用してください。 SecItemAdd の後に errSecDuplicateItem で SecItemUpdate を実行します。削除してから追加する方法を使用しないでください (レース ウィンドウを作成し、永続参照を破壊します)。重複ケースを処理しないで SecItemAdd を呼び出さないでください。→ keychain-fundamentals.md
7. 常に macOS でデータ保護キーチェーンをターゲットにしてください。 macOS ターゲットのすべての SecItem* 呼び出しで kSecUseDataProtectionKeychain: true を設定します。これがなければ、クエリはレガシーファイルベースのキーチェーンにサイレントにルーティングされ、異なる動作を持ち、サポートされていない属性を無視し、生体認証保護またはSecure Enclaveキーを使用できません。Mac CatalystおよびiOS-on-Macはこれを自動的に実行します。→ keychain-fundamentals.md
クイックリファレンステーブル
アクセシビリティ定数 — 選択ガイド
| 定数 | 復号化可能な場合 | バックアップ生存 | デバイス移行生存 | バックグラウンド安全 | 用途 |
|---|---|---|---|---|---|
WhenPasscodeSetThisDeviceOnly | ロック解除 + パスコード設定 | ❌ | ❌ | ❌ | 最高レベルのセキュリティシークレット; パスコード削除時に削除される |
WhenUnlockedThisDeviceOnly | ロック解除 | ❌ | ❌ | ❌ | バックグラウンド不要のデバイスバウンドシークレット |
WhenUnlocked | ロック解除 | ✅ | ✅ | ❌ | 同期可能なシークレット (システムデフォルト — 暗黙的使用を回避) |
AfterFirstUnlockThisDeviceOnly | 初回ロック解除後 → 再起動 | ❌ | ❌ | ✅ | バックグラウンドタスク、プッシュハンドラー、デバイスバウンド |
AfterFirstUnlock | 初回ロック解除後 → 再起動 | ✅ | ✅ | ✅ | リストア後に生き残る必要があるバックグラウンドタスク |
非推奨 (使用しないでください): kSecAttrAccessibleAlways、kSecAttrAccessibleAlwaysThisDeviceOnly — iOS 12で非推奨になりました。
ルーム・オブ・サムスール: バックグラウンドアクセスが必要ですか (プッシュハンドラー、バックグラウンド更新)? AfterFirstUnlockThisDeviceOnly から開始してください。フォアグラウンドのみですか? WhenUnlockedThisDeviceOnly から開始してください。高価値シークレットの場合は WhenPasscodeSetThisDeviceOnly に厳密化します。iCloud同期またはバックアップ移行が必要な場合のみ、非 ThisDeviceOnly バリアントを使用します。
CryptoKit アルゴリズム選択
| 必要な機能 | アルゴリズム | 最小iOS | 注 |
|---|---|---|---|
| データのハッシング | SHA256 / SHA384 / SHA512 | 13 | SHA3_256/SHA3_512 は iOS 18以上で利用可 |
| データの認証 (MAC) | HMAC<SHA256> | 13 | 常に定時間比較で検証してください (組み込み) |
| データの暗号化 (認証済み) | AES.GCM | 13 | 256ビットキー、96ビットノンス、128ビットタグ。同じキーでノンスを再利用しないでください |
| データの暗号化 (モバイル最適化) | ChaChaPoly | 13 | AES-NI なしのデバイス (古いApple Watch) でより優れたパフォーマンス |
| データの署名 | P256.Signing / Curve25519.Signing | 13 | 相互運用性の場合は P256、パフォーマンスの場合は Curve25519 を使用 |
| 鍵交換 | P256.KeyAgreement / Curve25519.KeyAgreement | 13 | 常に HKDF を通じて対称キーを導出してください — 生の共有シークレットを使用しないでください |
| ハイブリッド公開鍵暗号化 | HPKE | 17 | 手動の ECDH+HKDF+AES-GCM チェーンに置き換えます |
| ハードウェアバック署名 | SecureEnclave.P256.Signing | 13 | P256 のみ; キーはハードウェアから出ることはありません |
| ポスト量子鍵交換 | MLKEM768 | 26 | 形式的検証 (ML-KEM FIPS 203) |
| ポスト量子署名 | MLDSA65 | 26 | 形式的検証 (ML-DSA FIPS 204) |
| パスワード → 鍵導出 | PBKDF2 (via CommonCrypto) | 13 | ≥600,000回の反復 SHA-256 (OWASP 2024) |
| 鍵 → 鍵導出 | HKDF<SHA256> | 13 | 抽出してから展開; ドメイン分離のため常にinfoパラメータを使用してください |
アンチパターン検出 — クイックスキャン
コードをレビューする際に、これらのパターンを検索してください。いずれかの一致は検出です。
❌ = ユーザーコードで検出するため安全でないパターンシグネチャ。✅ = 参照ファイルで補正パターンを適用します。
| 検索対象 | アンチパターン | 重要度 | 参照 |
|---|---|---|---|
UserDefaults.standard.set + トークン/キー/シークレット/パスワード | プレーンテキスト認証情報ストレージ | CRITICAL | common-anti-patterns.md #1 |
| ソースにハードコードされた base64/16進数文字列 (≥16文字) | ハードコード暗号化キー | CRITICAL | common-anti-patterns.md #2 |
evaluatePolicy 近くに SecItemCopyMatching なし | LAContext のみ生体認証ゲート | CRITICAL | common-anti-patterns.md #3 |
リターン/ OSStatus チェック なしの SecItemAdd | 無視されたエラーコード | HIGH | common-anti-patterns.md #4 |
追加辞書に kSecAttrAccessible なし | 暗黙的アクセシビリティクラス | HIGH | common-anti-patterns.md #5 |
AES.GCM.Nonce() が同じキーでループ内 | ノンス再利用の可能性 | CRITICAL | common-anti-patterns.md #6 |
HKDF なしの sharedSecret.withUnsafeBytes | キーとしての生の共有シークレット | HIGH | common-anti-patterns.md #7 |
kSecAttrAccessibleAlways | 非推奨アクセシビリティ | HIGH | keychain-access-control.md |
SecureEnclave.isAvailable なしの #if !targetEnvironment(simulator) | シミュレータの偽陰性トラップ | MEDIUM | secure-enclave.md |
kSecAttrSynchronizable: true + ThisDeviceOnly | 矛盾する制約 | MEDIUM | keychain-item-classes.md |
SecTrustEvaluate (同期、非推奨) | レガシー信頼評価 | MEDIUM | certificate-trust.md |
kSecClassGenericPassword + kSecAttrServer | Web認証情報の間違ったクラス | MEDIUM | keychain-item-classes.md |
トップレベルレビューチェックリスト
14個のドメインすべてにわたる迅速な一掃のため、このチェックリストを使用してください。各項目は1つ以上のリファレンスファイルにマッピングされ、詳細な調査が可能です。ドメイン特定の詳細チェックの場合は、各リファレンスファイルの下部にあるサマリーチェックリストを使用してください。
-
1. シークレットはキーチェーンに、UserDefaults/plist/ソースにはない —
UserDefaults、Info.plist、.xcconfig、ハードコード文字列、またはNSCodingアーカイブに認証情報、トークン、または暗号化キーが存在しません。OWASP M9 (Insecure Data Storage) に直接違反しています。→common-anti-patterns.md#1–2、credential-storage-patterns.md、migration-legacy-stores.md、compliance-owasp-mapping.md -
2. すべての
OSStatusが確認されている — すべてのSecItem*呼び出しが網羅的なswitchまたは同等のもので戻りコードを処理します。無視されたリターンはありません。errSecInteractionNotAllowedは非破壊的に処理されます (後で再試行、決して削除しないでください)。→keychain-fundamentals.md、common-anti-patterns.md#4 -
3. 生体認証はキーチェーン連携 — 生体認証を使用する場合、認証は
LAContext.evaluatePolicy()のみではなく、SecAccessControl+ キーチェーンアクセスを通じて強制されます。→biometric-authentication.md、common-anti-patterns.md#3 -
4. アクセシビリティクラスが明示的で正しい — すべてのキーチェーンアイテムは、アクセスパターン (バックグラウンド対フォアグラウンド、デバイスバウンド対同期可能) と一致する明示的な
kSecAttrAccessible値を持ちます。非推奨Always定数はありません。→keychain-access-control.md -
5.
SecItem*呼び出しが@MainActorにない — すべてのキーチェーン操作は専用actorまたはバックグラウンドキューで実行します。UIコード、viewDidLoad、またはapplication(_:didFinishLaunchingWithOptions:)での同期キーチェーンアクセスはありません。→keychain-fundamentals.md -
6. 各アイテムタイプに正しい
kSecClass— Web認証情報は (GenericPassword ではなく)InternetPasswordを使用してAutoFillを実現します。暗号化キーは適切なkSecAttrKeyTypeを持つkSecClassKeyを使用します。アプリシークレットはkSecAttrService+kSecAttrAccountを持つGenericPasswordを使用します。→keychain-item-classes.md -
7. CryptoKit が正しく使用されている — ノンスは同じキーで再利用されません。ECDH共有シークレットは常に
HKDFを通じて導出してから対称キーとして使用されます。SymmetricKeyマテリアルはメモリまたはファイルではなく、キーチェーンに保存されます。暗号操作はプロトコルベースのユニットテストでカバーされます。→cryptokit-symmetric.md、cryptokit-public-key.md、testing-security-code.md -
8. Secure Enclave制約が遵守されている — SE キーは P256 のみ (古典)、インポートされません (常にオンデバイスで生成)、デバイスバウンド (バックアップ/同期なし)。可用性チェックはシミュレータと keychain-access-groups エンタイトルメント問題を防ぎます。→
secure-enclave.md -
9. 共有とアクセスグループが正しく設定されている —
kSecAttrAccessGroupは完全なTEAMID.group.identifier形式を使用します。エンタイトルメントはアプリと拡張機能の間で一致します。意図しないクロスアプリデータ公開はありません。→keychain-sharing.md -
10. 証明書信頼評価が最新である — (非推奨の同期
SecTrustEvaluateではなく)SecTrustEvaluateAsyncWithErrorを使用します。ピン留めストラテジーは SPKI ハッシュまたはNSPinnedDomains(年次ローテーションで壊れるリーフ証明書ピン留めではなく) を使用します。→certificate-trust.md -
11. macOS ターゲットがデータ保護キーチェーンである — すべての macOS
SecItem*呼び出しにはkSecUseDataProtectionKeychain: trueが含まれます (Mac Catalyst / iOS-on-Mac を除く、自動的に実行)。→keychain-fundamentals.md
リファレンスインデックス
| # | ファイル | 1行説明 | リスク |
|---|---|---|---|
| 1 | keychain-fundamentals.md | SecItem* CRUD、クエリ辞書、OSStatus処理、アクターベースのラッパー、macOS TN3137ルーティング | CRITICAL |
| 2 | keychain-item-classes.md | 5つの kSecClass タイプ、複合主キー、GenericPassword 対 InternetPassword、ApplicationTag 対 ApplicationLabel | HIGH |
| 3 | keychain-access-control.md | 7つのアクセシビリティ定数、SecAccessControl フラグ、データ保護層、NSFileProtection サイドバー | CRITICAL |
| 4 | biometric-authentication.md | キーチェーン連携生体認証、LAContext バイパス脆弱性、登録変更検出、フォールバックチェーン | CRITICAL |
| 5 | secure-enclave.md | ハードウェアバック P256 キー、CryptoKit SecureEnclave モジュール、永続化、シミュレータトラップ、iOS 26 ポスト量子 | HIGH |
| 6 | cryptokit-symmetric.md | SHA-2/3 ハッシング、HMAC、AES-GCM/ChaChaPoly 暗号化、SymmetricKey 管理、ノンス処理、HKDF/PBKDF2 | HIGH |
| 7 | cryptokit-public-key.md | ECDSA 署名、ECDH 鍵交換、HPKE (iOS 17+)、ML-KEM/ML-DSA ポスト量子 (iOS 26+)、曲線選択 | HIGH |
| 8 | credential-storage-patterns.md | OAuth2/OIDC トークンライフサイクル、APIキーストレージ、リフレッシュトークンローテーション、ランタイムシークレット、ログアウトクリーンアップ | CRITICAL |
| 9 | keychain-sharing.md | アクセスグループ、チームID プレフィックス、アプリ拡張機能、キーチェーン共有対アプリグループエンタイトルメント、iCloud同期 | MEDIUM |
| 10 | certificate-trust.md | SecTrust 評価、SPKI/CA/リーフピン留め、NSPinnedDomains、クライアント証明書 (mTLS)、信頼ポリシー | HIGH |
| 11 | migration-legacy-stores.md | UserDefaults/plist/NSCoding → キーチェーン移行、安全な削除、初回起動クリーンアップ、バージョン管理された移行 | MEDIUM |
| 12 | common-anti-patterns.md | AI生成セキュリティミスの最上位10、❌/✅ コードペア、検出ヒューリスティック、OWASPマッピング | CRITICAL |
| 13 | testing-security-code.md | プロトコルベースのモック、シミュレータ対デバイス差、CI/CD キーチェーン、Swift Testing、ミューテーションテスト | MEDIUM |
| 14 | compliance-owasp-mapping.md | OWASP Mobile Top 10 (2024)、MASVS v2.1.0、MASTG テストID、M1/M3/M9/M10 マッピング、監査対応 | MEDIUM |
権威あるソース
これらはすべてのリファレンスファイルの基礎となる主要ソースです。疑わしい場合は、これらを他のセカンダリソースより優先してください。
- Apple Keychain Services ドキュメンテーション — 標準API リファレンス
- Apple Platform Security Guide (毎年更新) — アーキテクチャと暗号化設計
- TN3137: "On Mac Keychain APIs and Implementations" — macOS データ保護対ファイルベースキーチェーン
- Quinn "The Eskimo!" DTS Posts — "SecItem: Fundamentals" と "SecItem: Pitfalls and Best Practices" (2025年まで更新)
- WWDC 2019 Session 709 — "Cryptography and Your Apps" (CryptoKit 導入)
- WWDC 2025 Session 314 — "Get ahead with quantum-secure cryptography" (ML-KEM、ML-DSA)
- OWASP Mobile Top 10 (2024) + MASVS v2.1.0 + MASTG v2 — コンプライアンスフレームワーク
- CISA/FBI "Product Security Bad Practices" v2.0 (2025年1月) — ハードコード認証情報は国家安全保障リスクとして分類
エージェント動作ルール
以下のセクションは、このスキルを使用する際にAIエージェントがどのように動作するべきかを規定します: スコープ内外、トーン調整、回避すべき一般的な間違い、リファレンスファイルの選択方法、および出力フォーマット要件。
スコープ境界 — 包含範囲
このスキルは iOS、macOS、tvOS、watchOS、visionOS 上のクライアント側Apple プラットフォームセキュリティ に対して権威あります:
- Keychain Services —
SecItemAdd、SecItemCopyMatching、SecItemUpdate、SecItemDelete、クエリ辞書構築、OSStatus処理、アクター/スレッド分離、macOS 上のデータ保護キーチェーン (TN3137) - キーチェーンアイテムクラス —
kSecClassGenericPassword、kSecClassInternetPassword、kSecClassKey、kSecClassCertificate、kSecClassIdentity、複合主キー、AutoFill 統合 - アクセス制御 — 7つの
kSecAttrAccessible定数、SecAccessControlCreateWithFlags、データ保護層、NSFileProtection対応 - 生体認証 —
LAContext+ キーチェーン連携、ブール値ゲート脆弱性、登録変更検出、フォールバックチェーン、evaluatedPolicyDomainState - Secure Enclave — CryptoKit
SecureEnclave.P256モジュール、ハードウェア制約 (P256のみ、インポートなし、エクスポートなし、対称なし)、キーチェーンを通じた永続化、シミュレータトラップ、iOS 26 ポスト量子 (ML-KEM、ML-DSA) - CryptoKit 対称 — SHA-2/SHA-3 ハッシング、HMAC、AES-GCM、ChaChaPoly、
SymmetricKeyライフサイクル、ノンス処理、HKDF、PBKDF2 - CryptoKit 公開鍵 — ECDSA 署名 (P256/Curve25519)、ECDH 鍵交換、HPKE (iOS 17+)、ML-KEM/ML-DSA (iOS 26+)、曲線選択
- 認証情報ストレージパターン — OAuth2/OIDC トークンライフサイクル、APIキーストレージ、リフレッシュトークンローテーション、ランタイムシークレット取得、ログアウトクリーンアップ
- キーチェーン共有 — アクセスグループ、チームIDプレフィックス、
keychain-access-groups対com.apple.security.application-groupsエンタイトルメント、拡張機能、iCloud キーチェーン同期 - 証明書信頼 —
SecTrust評価、SPKI/CA/リーフピン留め、NSPinnedDomains、クライアント証明書 (mTLS)、信頼ポリシー - 移行 — UserDefaults/plist/NSCoding → キーチェーン移行、安全なレガシー削除、初回起動クリーンアップ、バージョン管理された移行
- テスト — プロトコルベースのモック、シミュレータ対デバイス差、CI/CD キーチェーン作成、Swift Testing パターン
- コンプライアンス — OWASP Mobile Top 10 (2024)、MASVS v2.1.0、MASTG v2 テストID、CISA/FBI Bad Practices
スコープ内のエッジケース: mTLSピン留めのためのクライアント側証明書ロード (certificate-trust.md)。Keychain での Passkey/AutoFill 認証情報ストレージ (keychain-item-classes.md、credential-storage-patterns.md)。@AppStorage は安全でないストレージとしてフラグが付けられます — キーチェーンにリダイレクトします (common-anti-patterns.md)。
スコープ境界 — 除外範囲
このスキルを使用して以下のトピックに答え ないでください。簡潔に、それらがスコープ外である理由を説明し、どこを見るかをお勧めします。
| トピック | 除外理由 | リダイレクト先 |
|---|---|---|
| App Transport Security (ATS) | サーバー側TLS ポリシー、クライアントキーチェーンではない | Apple の ATS ドキュメンテーション、Info.plist NSAppTransportSecurity リファレンス |
| CloudKit 暗号化 | サーバー管理キー階層、クライアント CryptoKit ではない | CloudKit ドキュメンテーション、CKRecord.encryptedValues |
| ネットワークセキュリティ / URLSession TLS 設定 | トランスポート層、ストレージ層ではない | Apple URL Loading System ドキュメンテーション; このスキルはクライアント証明書ロードのみカバーします mTLS 用 |
| サーバー側認証アーキテクチャ | バックエンド JWT 発行、OAuth プロバイダー設定 | OWASP ASVS (Application Security Verification Standard) |
| WebAuthn / passkeys サーバー側 | 依存者パーティの実装 | Apple "Supporting passkeys" ドキュメンテーション; このスキルはクライアント側 ASAuthorizationController をカバーしています。キーチェーンに認証情報を保存する場合のみ |
| コード署名 / プロビジョニングプロファイル | ビルド/配布、ランタイムセキュリティではない | Apple コード署名ドキュメンテーション |
| 脱獄検出 | ランタイム整合性、暗号化ストレージではない | OWASP MASTG MSTG-RESILIENCE カテゴリ |
SwiftUI @AppStorage | UserDefaults ラッパー — スコープ外 (シークレット用として不安全とフラグする場合を除く) | common-anti-patterns.md #1 はこれをフラグします; 深いカバレッジはなし |
| クロスプラットフォーム暗号 (OpenSSL、LibSodium) | サードパーティライブラリ、Apple フレームワークではない | 各ライブラリのドキュメンテーション |
トーンルール
このスキルは 無党派的で正確性重視 です。トーンは重要度に基づいて調整されます。
デフォルトトーン — 勧告的。 以下のため「検討」、「提案」、「1つのアプローチは」、「一般的なパターンは」を使用してください: アーキテクチャの選択 (ラッパークラス設計、アクター対 DispatchQueue)、複数の有効なオプションが存在する場合のアルゴリズム選択 (P256 対 Curve25519、AES-GCM 対 ChaChaPoly)、脅威モデルが不明な場合のアクセシビリティクラス選択、テストストラテジー、コード編成。
昇格したトーン — 指示的。 只 以下の7つのコアガイドライン上記と common-anti-patterns.md の10個のアンチパターン のため「常に」、「決して」、「必須」を使用してください。これらはセキュリティ不変式であり、スタイル設定の嗜好ではありません。指示の網羅的なリストは以下のとおりです:
OSStatusを決して無視しないでください — 常にSecItem*呼び出しから戻りコードを確認してください。→keychain-fundamentals.md- スタンドアロン認証ゲートとして
LAContext.evaluatePolicy()を決して使用しないでください — 常に生体認証をキーチェーンアイテムにバインドしてください。→biometric-authentication.md UserDefaults、Info.plist、.xcconfig、またはNSCodingアーカイブにシークレットを決して保存しないでください。→credential-storage-patterns.md、common-anti-patterns.md@MainActorでSecItem*を決して呼び出さないでください — 常にバックグラウンドアクターまたはキューを使用してください。→keychain-fundamentals.md- 常にすべての
SecItemAddでkSecAttrAccessibleを明示的に設定してください。→keychain-access-control.md - 常に追加または更新パターンを使用してください (
SecItemAdd→errSecDuplicateItemでSecItemUpdate)。→keychain-fundamentals.md - 常に macOS ターゲットで
kSecUseDataProtectionKeychain: trueを設定してください。→keychain-fundamentals.md - 同じ AES-GCM キーでノンスを決して再利用しないでください。→
cryptokit-symmetric.md、common-anti-patterns.md - 対称鍵として生の ECDH 共有シークレットを決して使用しないでください — 常に HKDF を通じて導出してください。→
cryptokit-public-key.md、common-anti-patterns.md - セキュリティ目的のため
Insecure.MD5またはInsecure.SHA1を決して使用しないでください。→cryptokit-symmetric.md、common-anti-patterns.md
パターンがこのリストにない場合、勧告的なトーンを使用してください。参照ファイルがサポートしないもの以上に警告を昇格させないでください。
辞退する際のトーン。 クエリがスコープ外の場合は、解除的ではなく直接的です: 「このスキルはクライアント側キーチェーンと CryptoKit をカバーします。ATS 設定については、Apple の NSAppTransportSecurity ドキュメンテーションが正しいリファレンスです。」境界を述べ、代替案を提案し、進めます。
一般的なAI間違い — 最も可能性の高い不正確な出力の10個
最終出力の前に、すべての10個をスキャンしてください。各エントリは正しいパターンを含むリファレンスファイルに意図的に対になっています。
間違い #1 — 単なる生体認証ゲートとして LAContext.evaluatePolicy() を生成する。 AIはブール値コールバックパターンを生成します。ここで evaluatePolicy は success: Bool を返し、アプリはそのブール値でアクセスをゲートします。ブール値はフック可能なユーザースペースメモリに存在します — Frida/objection はそれを1つのコマンドでバイパスします。✅ 正しいパターン: SecAccessControl と .biometryCurrentSet を持つシークレットを保存し、SecItemCopyMatching を通じて検索します。→ biometric-authentication.md
間違い #2 — シミュレータガードなしで SecureEnclave.isAvailable を提案する。 AI は if SecureEnclave.isAvailable { ... } を #if !targetEnvironment(simulator) なしで生成します。シミュレータでは、isAvailable は false を返します。シミュレータのすべてのテストで、フォールバックパスがサイレントに実行されます。✅ 正しいパターン: #if targetEnvironment(simulator) を使用してコンパイル時に明確なエラーをスロー/リターンし、SecureEnclave.isAvailable はデバイスビルドでのみチェックしてください。→ secure-enclave.md
間違い #3 — Secure Enclaveへの外部キーのインポート。 AI は SecureEnclave.P256.Signing.PrivateKey(rawRepresentation: someData) を生成します。SE キーはハードウェア内で生成される必要があります — SE タイプには init(rawRepresentation:) がありません。init(dataRepresentation:) は以前に作成された SE キーの不透明な暗号化Blob のみを受け入れます。✅ 正しいパターン: SE 内で生成し、不透明な dataRepresentation をキーチェーンに永続化し、init(dataRepresentation:) で復元してください。→ secure-enclave.md
間違い #4 — 対称暗号化に SecureEnclave.AES または SE を使用する。 AI は存在しない SE 対称 API への参照を生成します。SE の内部 AES エンジンは開発者 API として公開されていません。iOS 26 より前では、SE は P256 署名と鍵交換のみをサポートします。iOS 26 では ML-KEM と ML-DSA が追加されます。対称プリミティブではありません。✅ 正しいパターン: 署名/鍵交換に SE を使用; ECDH + HKDF を通じて SymmetricKey を導出して暗号化します。→ secure-enclave.md、cryptokit-symmetric.md
間違い #5 — SecItemAdd で kSecAttrAccessible を省略する。 AI は辞書をアクセシビリティ属性なしで追加構築します。システムはデフォルトで kSecAttrAccessibleWhenUnlocked を適用します。これはバックグラウンド操作を破壊し、セキュリティポリシーをコードレビューで見えなくします。✅ 正しいパターン: 常に kSecAttrAccessible を明示的に設定してください。→ keychain-access-control.md
間違い #6 — errSecDuplicateItem を処理しないで SecItemAdd を使用する。 AI は errSecSuccess のチェックのみ、または削除してから追加を使用します。重複処理なしで、2番目の保存はサイレントに失敗します。削除してから追加はレースウィンドウを作成し、永続参照を破壊します。✅ 正しいパターン: 追加または更新パターン。→ keychain-fundamentals.md
間違い #7 — AES-GCM暗号化のため明示的なノンスを指定する。 AI はノンスを手動で作成し、AES.GCM.seal に渡します。手動のノンス管理は再利用を招きます — 単一の再利用は両方のプレーンテキストの XOR を明かします。CryptoKit はパラメータを省略すると暗号化的にランダムなノンスを自動的に生成します。✅ 正しいパターン: AES.GCM.seal(plaintext, using: key) を nonce: パラメータなしで呼び出してください。→ cryptokit-symmetric.md、common-anti-patterns.md #6
間違い #8 — 対称鍵として生の ECDH 共有シークレットを使用する。 AI は sharedSecretFromKeyAgreement の出力を取り、withUnsafeBytes を通じて直接使用します。生の共有シークレットは非均一分布を持ちます。CryptoKit の SharedSecret は意図的に withUnsafeBytes を持たありません — このコードは安全でない回避策を必要とします。これは誤用の明確な信号です。✅ 正しいパターン: 常に sharedSecret.hkdfDerivedSymmetricKey(...) を通じて導出してください。→ cryptokit-public-key.md、common-anti-patterns.md #7
間違い #9 — SHA-3が iOS 26を必要とすると主張する。 AI はポスト量子 WWDC 2025追加を SHA-3 追加と混同します。SHA-3 ファミリタイプは iOS 18 / macOS 15 で追加されました。iOS 26 では ML-KEM と ML-DSA が導入されました。SHA-3 ではなく。✅ 正しいバージョンタグ: SHA-3 → iOS 18+。ML-KEM/ML-DSA → iOS 26+。→ cryptokit-symmetric.md
間違い #10 — 初回起動キーチェーンクリーンアップがない。 AI は標準 @main struct MyApp: App なしでキーチェーンクリーンアップを生成します。キーチェーンアイテムはアプリアンインストール後も生存します。再インストールされたアプリは古いトークン、期限切れキー、孤立した認証情報を継承します。✅ 正しいパターン: UserDefaults フラグをチェックし、初回起動時に5つの kSecClass タイプ全体で SecItemDelete を実行してください。→ common-anti-patterns.md #9、migration-legacy-stores.md
リファレンスファイル読み込みルール
クエリに必要な 最小セット をロードしてください。すべての14個をロードしないでください — 7,000行以上で、フォーカスは希釈されます。
| クエリタイプ | これらのファイルをロード | 理由 |
|---|---|---|
| 「キーチェーンコードをレビューしてください」 | common-anti-patterns.md → コードが実行することに基づいてドメイン特定ファイル | アンチパターンファイルはレビューのバックボーン |
| 「この生体認証は安全ですか?」 | biometric-authentication.md + common-anti-patterns.md (#3) | ブール値ゲートは #1 生体認証リスク |
| 「トークン / パスワードを保存」 | keychain-fundamentals.md + credential-storage-patterns.md | CRUD + ライフサイクル |
| 「データを暗号化 / ハッシング」 | cryptokit-symmetric.md | 対称操作 |
| 「データに署名 / 鍵交換」 | cryptokit-public-key.md | 非対称操作 |
| 「Secure Enclaveを使用」 | secure-enclave.md + keychain-fundamentals.md | SE キーはキーチェーン永続化が必要 |
| 「拡張機能とのキーチェーン共有」 | keychain-sharing.md + keychain-fundamentals.md | アクセスグループ + CRUD |
| 「UserDefaultsから移行」 | migration-legacy-stores.md + credential-storage-patterns.md | 移行 + ターゲットパターン |
| 「TLSピン留め / mTLS」 | certificate-trust.md | 信頼評価 |
| 「どの kSecClass?」 | keychain-item-classes.md | クラス選択 + 主キー |
| 「データ保護を設定」 | keychain-access-control.md | アクセシビリティ定数 |
| 「キーチェーンコードのテストを作成」 | testing-security-code.md | プロトコルモック + CI/CD |
| 「OWASP コンプライアンス監査」 | compliance-owasp-mapping.md + common-anti-patterns.md | マッピング + 検出 |
| 「完全なセキュリティレビュー」 | common-anti-patterns.md + コードが対象とするすべてのファイル | アンチパターンから開始、拡張 |
読み込み順序: (1) クエリに最も特定のファイル。(2) レビュー/監査のため common-anti-patterns.md を追加。(3) あらゆる SecItem* タスクのため keychain-fundamentals.md を追加。(4) OWASP/監査が言及されている場合のみ compliance-owasp-mapping.md を追加。(5) ファイルを推測的にロードしないでください。
出力形式ルール
**1. 常に ✅/❌
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- ivan-magda
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/ivan-magda/swift-security-skill / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。