Token导航 LogoToken导航TokenDH.com
研究检索敏感数据github未标认证来源可访问许可证需确认审计通过

axiom-keychain公理钥匙扣

Agent Skill

axiom-keychain 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

861

周安装

37

GitHub Stars

873

下载量

302
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:axiom-keychain(公理钥匙扣)
来源仓库:https://github.com/charleswiltgen/axiom
仓库路径:skills/axiom-keychain
安装命令:
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-keychain
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-keychain

简介

用于查找、检索和筛选相关信息。

  • 适合在 Codex、Claude、Cursor、Gemini CLI 中根据关键词、任务场景或来源线索快速定位候选结果。
  • 可结合来源仓库、安装命令和原始 README 继续核验具体用法。
  • 安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。
  • axiom-keychain 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Keychain Services

Secure credential storage, SecItem API mental model, uniqueness constraints, data protection classes, biometric access control, keychain sharing, and Mac keychain differences for iOS/macOS apps.

When to Use This Skill

Use when you need to:

  • ☑ Store tokens, passwords, API keys, or cryptographic keys securely
  • ☑ Debug errSecDuplicateItem, errSecItemNotFound, or errSecInteractionNotAllowed
  • ☑ Choose the right kSecAttrAccessible level for your use case
  • ☑ Add biometric or passcode protection to a keychain item
  • ☑ Share credentials between apps or app extensions via access groups
  • ☑ Migrate from UserDefaults/@AppStorage to keychain for sensitive data
  • ☑ Understand why SecItemCopyMatching returns something different than expected
  • ☑ Store or retrieve keychain items from a background context

Example Prompts

"How do I store an auth token in the keychain?" "errSecDuplicateItem when saving to keychain but the item doesn't exist" "My keychain read fails in background refresh" "How do I add Face ID protection to a keychain item?" "Share keychain items between my app and widget extension" "What's the difference between kSecAttrAccessibleAfterFirstUnlock and WhenUnlocked?" "SecItemCopyMatching returns errSecItemNotFound but I just saved it" "How do I use the keychain on macOS with Catalyst?" "My keychain wrapper is returning nil — how do I debug this?" "errSecInteractionNotAllowed in background task"

Red Flags

Signs you're making this harder than it needs to be:

  • ❌ Using a keychain wrapper without understanding SecItem — Wrappers hide the 4-function model and introduce their own bugs. Quinn "The Eskimo!" explicitly warns: most wrapper issues stem from the wrapper, not the keychain. Learn the model first.
  • ❌ Storing tokens in UserDefaults or @AppStorage — These are plist files readable by anyone with device access (or a backup). Credentials belong in the keychain. No exceptions.
  • ❌ Force-unwrapping SecItemCopyMatching results — The return type depends on which kSecReturn* flags you passed. A mismatch gives you a surprising type, not your data.
  • ❌ Not specifying kSecAttrAccessible — Defaults to kSecAttrAccessibleWhenUnlocked, which fails in background execution. If your app does background refresh, push processing, or VoIP, this will bite you.
  • ❌ Catching errSecDuplicateItem by deleting then re-adding — This creates a race condition and destroys metadata (creation date, access control). Use SecItemUpdate instead.
  • ❌ Using kSecMatchLimitAll without understanding delete semantics — SecItemDelete has no kSecMatchLimit; it deletes ALL matching items. One careless query can wipe credentials.
  • ❌ Ignoring errSecDuplicateItem — "It worked last time" means you have a query/uniqueness mismatch. This is the #1 keychain bug.

The 4-Function Model

Quinn's mental model: the keychain is a database with per-class tables. The four SecItem functions map directly to SQL.

SecItem FunctionSQL EquivalentPurpose
SecItemAddINSERTCreate a new item
SecItemCopyMatchingSELECTRead one or more items
SecItemUpdateUPDATEModify an existing item
SecItemDeleteDELETERemove items

Per-Class Tables

Each item class is a separate table with different columns (attributes):

ClasskSecClass ValueTypical Use
Generic passwordkSecClassGenericPasswordApp credentials, tokens, secrets
Internet passwordkSecClassInternetPasswordURL-associated credentials
CertificatekSecClassCertificateX.509 certificates
KeykSecClassKeyCryptographic keys
IdentitykSecClassIdentityCertificate + private key pair

For most iOS apps, you only need kSecClassGenericPassword. Internet passwords are for credentials tied to a specific server/protocol/port. Certificates and keys are for custom cryptographic operations.

Uniqueness Constraints

This is where most keychain bugs originate. Each class has a primary key — a combination of attributes that must be unique.

Generic Password Primary Key

kSecAttrService + kSecAttrAccount + kSecAttrAccessGroup

Internet Password Primary Key

kSecAttrServer + kSecAttrAccount + kSecAttrPort
  + kSecAttrProtocol + kSecAttrAuthenticationType + kSecAttrSecurityDomain
  + kSecAttrAccessGroup

See axiom-keychain-ref for the full attribute breakdown per class.

The errSecDuplicateItem Trap

You call SecItemCopyMatching with a query and get errSecItemNotFound. You call SecItemAdd with what you think is the same item. You get errSecDuplicateItem. How?

The query attributes don't match the uniqueness attributes. Your copy query might search by kSecAttrService alone, but uniqueness is service + account + accessGroup. An item exists with the same service but a different account — your query misses it, but your add hits the uniqueness constraint on the combination.

// This query finds nothing (searching by service + label, but label isn't a primary key)
let copyQuery: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.auth",
    kSecAttrLabel as String: "auth-token",
    kSecReturnData as String: true
]
// Result: errSecItemNotFound (no item has this label)

// This add fails — an item with service "com.app.auth" + account "user-token"
// already exists. The add hits the primary key (service + account + accessGroup).
let addQuery: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.auth",
    kSecAttrAccount as String: "user-token",
    kSecValueData as String: tokenData
]
// Result: errSecDuplicateItem

Fix: Always specify ALL primary key attributes in every query. For generic passwords, always include kSecAttrService AND kSecAttrAccount.

The Safe Add-or-Update Pattern

func saveToKeychain(service: String, account: String, data: Data) -> OSStatus {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrService as String: service,
        kSecAttrAccount as String: account
    ]

    let attributes: [String: Any] = [
        kSecValueData as String: data
    ]

    // Try update first
    var status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary)

    if status == errSecItemNotFound {
        // Item doesn't exist — add it
        var addQuery = query
        addQuery[kSecValueData as String] = data
        status = SecItemAdd(addQuery as CFDictionary, nil)
    }

    return status
}

This is safer than delete-then-add because it preserves item metadata and avoids race conditions.

Parameter Block Anatomy

Every SecItem function takes a dictionary. That dictionary contains properties from 5 groups, but which groups are valid depends on which function you're calling.

The 5 Property Groups

GroupPrefix/PatternPurpose
ClasskSecClassWhich table (generic password, key, etc.)
AttributeskSecAttr*Column values (service, account, label)
SearchkSecMatch*Query modifiers (limit, case sensitivity)
Return typekSecReturn*What shape the result takes
Value typekSecValue*The actual data/reference

Which Groups Apply to Which Function

digraph param_blocks {
    rankdir=LR;

    "SecItemAdd" [shape=box];
    "SecItemCopyMatching" [shape=box];
    "SecItemUpdate\n(query dict)" [shape=box];
    "SecItemUpdate\n(attributes dict)" [shape=box];
    "SecItemDelete" [shape=box];

    "Class" [shape=ellipse];
    "Attributes" [shape=ellipse];
    "Search" [shape=ellipse];
    "Return type" [shape=ellipse];
    "Value type" [shape=ellipse];

    "SecItemAdd" -> "Class";
    "SecItemAdd" -> "Attributes";
    "SecItemAdd" -> "Return type";
    "SecItemAdd" -> "Value type";

    "SecItemCopyMatching" -> "Class";
    "SecItemCopyMatching" -> "Attributes";
    "SecItemCopyMatching" -> "Search";
    "SecItemCopyMatching" -> "Return type";

    "SecItemUpdate\n(query dict)" -> "Class";
    "SecItemUpdate\n(query dict)" -> "Attributes";
    "SecItemUpdate\n(query dict)" -> "Search";

    "SecItemUpdate\n(attributes dict)" -> "Attributes";
    "SecItemUpdate\n(attributes dict)" -> "Value type";

    "SecItemDelete" -> "Class";
    "SecItemDelete" -> "Attributes";
    "SecItemDelete" -> "Search";
}

kSecMatchLimit Defaults

This is a documented pitfall from Quinn's thread. The default value of kSecMatchLimit depends on context:

ContextDefault kSecMatchLimitBehavior
SecItemCopyMatching with kSecReturnDatakSecMatchLimitOneReturns one item
SecItemCopyMatching with kSecReturnAttributeskSecMatchLimitOneReturns one item
SecItemCopyMatching with kSecReturnRefkSecMatchLimitOneReturns one item
SecItemDeleteNo limit conceptDeletes ALL matches

SecItemDelete has no kSecMatchLimit parameter. It deletes every item matching your query. If your query is broad (only kSecClass and kSecAttrService), you will delete every item for that service across all accounts.

Return Type Determines Output Type

kSecReturn* FlagsOutput Type
kSecReturnData onlyCFData (the raw secret)
kSecReturnAttributes onlyCFDictionary (item metadata)
kSecReturnRef onlySecKey / SecCertificate / SecIdentity
kSecReturnData + kSecReturnAttributesCFDictionary (metadata + kSecValueData key)
kSecReturnPersistentRefCFData (persistent reference, survives keychain resets)

Force-casting the result to the wrong type is a common crash source. Always match your cast to your return flags.

Accessibility and Data Protection

kSecAttrAccessible controls when the keychain item's decryption key is available. This maps directly to the device's data protection classes.

LevelAvailable WhenUse Case
kSecAttrAccessibleWhenUnlockedDevice unlockedDefault. UI-driven credentials
kSecAttrAccessibleWhenUnlockedThisDeviceOnlyDevice unlocked, no backupHigh-security tokens
kSecAttrAccessibleAfterFirstUnlockAfter first unlock until rebootBackground refresh, push processing
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnlyAfter first unlock, no backupBackground + high security
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnlyPasscode set + unlockedBiometric-gated items

The Background Execution Trap

This is the single most common keychain failure in production. Your app works perfectly during normal use but fails with errSecInteractionNotAllowed (-25308) during background refresh.

The dangerous pattern:

// Background task tries to read a token
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.auth",
    kSecAttrAccount as String: "refresh-token",
    kSecReturnData as String: true
    // Item was stored with default WhenUnlocked accessibility (set at add time)
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
// status == errSecInteractionNotAllowed when device is locked

// Developer's instinct: "the token is corrupted, delete and re-auth"
if status != errSecSuccess {
    SecItemDelete(query as CFDictionary)  // DELETES THE CREDENTIAL
}

From Quinn: "This is a lesson that, once learnt, is never forgotten!"

The item is fine. The device is locked, so the decryption key isn't available. The developer's error handler destroys a perfectly valid credential because it misinterprets the error.

The fix: Store tokens needed in background with kSecAttrAccessibleAfterFirstUnlock:

let addQuery: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.auth",
    kSecAttrAccount as String: "refresh-token",
    kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock,
    kSecValueData as String: tokenData
]

And never delete on errSecInteractionNotAllowed — it means "try again when the device is unlocked", not "this item is broken".

Access Control and Biometrics

SecAccessControl gates individual keychain items behind biometric authentication or device passcode.

Creating a Biometric-Gated Item

var error: Unmanaged<CFError>?
guard let accessControl = SecAccessControlCreateWithFlags(
    nil,
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
    .biometryCurrentSet,
    &error
) else {
    // Handle error — usually means device has no passcode
    return
}

let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.auth",
    kSecAttrAccount as String: "biometric-secret",
    kSecAttrAccessControl as String: accessControl,
    kSecValueData as String: secretData
]

let status = SecItemAdd(query as CFDictionary, nil)

Access Control Flag Selection

digraph acl_decision {
    "What gates access?" [shape=diamond];
    "Enrollment change\nmatters?" [shape=diamond];
    "Biometric or\npasscode fallback?" [shape=diamond];

    ".biometryCurrentSet" [shape=box, label=".biometryCurrentSet\nInvalidates if fingerprints/face change"];
    ".biometryAny" [shape=box, label=".biometryAny\nSurvives enrollment changes"];
    ".userPresence" [shape=box, label=".userPresence\nBiometry with passcode fallback"];
    ".devicePasscode" [shape=box, label=".devicePasscode\nPasscode only, no biometry"];

    "What gates access?" -> "Enrollment change\nmatters?" [label="biometry"];
    "What gates access?" -> ".devicePasscode" [label="passcode only"];
    "What gates access?" -> "Biometric or\npasscode fallback?" [label="either"];
    "Enrollment change\nmatters?" -> ".biometryCurrentSet" [label="yes, re-auth\non change"];
    "Enrollment change\nmatters?" -> ".biometryAny" [label="no, any enrolled\nbiometry"];
    "Biometric or\npasscode fallback?" -> ".userPresence" [label="user convenience"];
}
FlagBehaviorWhen to Use
.biometryCurrentSetInvalidated if biometry enrollment changesBanking, medical — re-auth on new fingerprint/face
.biometryAnySurvives enrollment changesConvenience auth, app lock
.userPresenceBiometry with passcode fallbackMost common choice — works even if biometry fails
.devicePasscodePasscode only, no biometry promptAccessibility-first or biometry-averse users

LAContext for Reuse Duration

By default, each keychain read prompts for biometric auth. To allow reuse within a time window:

let context = LAContext()
context.touchIDAuthenticationAllowableReuseDuration = 10  // seconds

let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.auth",
    kSecAttrAccount as String: "biometric-secret",
    kSecUseAuthenticationContext as String: context,
    kSecReturnData as String: true
]

After one successful biometric auth, subsequent reads within 10 seconds skip the prompt. Maximum reuse duration is LATouchIDAuthenticationMaximumAllowableReuseDuration (5 minutes on current hardware).

Sharing and Access Groups

Keychain Access Groups vs App Groups

FeatureKeychain Access GroupsApp Groups
Entitlementkeychain-access-groupscom.apple.security.application-groups
PrefixTeam ID (auto-added)No prefix (you control full string)
ScopeKeychain items onlyFiles, UserDefaults, AND keychain
SetupSigning & Capabilities → Keychain SharingSigning & Capabilities → App Groups

How Access Groups Work

Every keychain item belongs to exactly one access group. If you don't specify kSecAttrAccessGroup, the item goes into your app's default access group (TEAMID.your.bundle.id).

To share between apps or extensions:

  1. Add the same keychain access group to both targets (Signing & Capabilities → Keychain Sharing)
  2. Specify the group when writing:
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.shared-auth",
    kSecAttrAccount as String: "user-token",
    kSecAttrAccessGroup as String: "TEAMID.com.app.shared",
    kSecValueData as String: tokenData
]

The Team ID Prefix Trap

Keychain access groups get the Team ID automatically prepended by the system. You write com.app.shared in the entitlement, the system stores it as ABCD1234.com.app.shared.

But kSecAttrAccessGroup in your code must include the prefix: "ABCD1234.com.app.shared".

App Groups do NOT get this prefix. If you're using an App Group for keychain sharing (via kSecAttrAccessGroup with a group. prefix), use the full string as-is.

The App ID Prefix Change Trap

From Quinn's pitfalls: if an app changes its App ID prefix (Team ID), it loses access to all existing keychain items. This happens when:

  • Transferring an app between developer accounts
  • Certain legacy App ID configurations

There is no recovery. The items are orphaned. Plan for this in migration logic — detect the condition and prompt the user to re-authenticate.

Mac Keychain Differences

macOS has two keychain systems. Understanding the difference prevents "it works on iOS but fails on Mac" bugs.

File-Based Keychain (Legacy)

The traditional macOS keychain (~/Library/Keychains/login.keychain-db):

  • User-visible in Keychain Access.app
  • Supports ACLs (access control lists) for per-app access
  • Items can be shared across all apps by default
  • No data protection classes

Data Protection Keychain (Modern)

Aligned with iOS keychain behavior (from TN3137):

  • Not visible in Keychain Access.app (prior to macOS 15)
  • Uses data protection classes (kSecAttrAccessible)
  • Items scoped to access groups (same as iOS)
  • Required for Catalyst and SwiftUI multiplatform apps

Always Use Data Protection Keychain

let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "com.app.auth",
    kSecAttrAccount as String: "token",
    kSecUseDataProtectionKeychain as String: true,  // Critical for Mac
    kSecValueData as String: tokenData
]

Set kSecUseDataProtectionKeychain: true for ALL keychain operations on macOS. This gives you consistent behavior across iOS, macOS, Catalyst, and Mac Catalyst.

Without this flag on macOS, items go into the file-based keychain where:

  • Access control behaves differently (ACLs instead of data protection)
  • Sharing semantics change (any app can read by default)
  • Items appear in Keychain Access.app (user confusion)
  • Migration between file-based and data-protection keychains is one-way and manual

Anti-Rationalization

RationalizationWhy It FailsTime Cost
"UserDefaults is fine for tokens, it's a private app"Backup extraction, device access tools, and MDM profiles all read UserDefaults. The keychain is encrypted at the hardware level.4-8 hours for a security incident response
"I'll wrap it in a KeychainHelper class to simplify things"Wrappers abstract the 4-function model, hiding uniqueness and parameter block semantics. When they break, you debug the wrapper AND the keychain.2-4 hours debugging a wrapper bug vs 30 min learning SecItem
"Delete then re-add is simpler than update"Destroys creation date, access control settings, and persistent references. Creates a TOCTOU race if another process reads between delete and add.1-2 hours debugging intermittent failures
"WhenUnlocked is secure enough"Correct for UI-driven reads. Fatal for background refresh, push processing, silent notifications. errSecInteractionNotAllowed at 3 AM with no user to unlock.2-6 hours diagnosing a background failure that only reproduces on locked devices
"I tested it on Simulator, it works"Simulator has no Secure Enclave, no data protection enforcement, and different keychain behavior. Biometric items always succeed. Accessibility constraints are not enforced.4-8 hours debugging device-only failures
"errSecInteractionNotAllowed means the token is corrupted"It means the device is locked. The token is fine. Deleting it destroys a valid credential and forces re-authentication.15-30 min user complaint cycle per incident
"Access groups are too complicated, I'll use App Groups for everything"App Groups add keychain sharing as a side effect, but the semantics differ from keychain access groups. Team ID prefix behavior is different. Mixing both creates invisible access scope bugs.2-4 hours debugging cross-target access failures

Pressure Scenarios

Scenario 1: "Just store it in UserDefaults for now"

Context: Sprint deadline, new feature requires storing an API token. Keychain code looks complicated.

Pressure: "UserDefaults is faster to implement. We'll move it to keychain in the security sprint."

Reality: Moving from UserDefaults to keychain later requires migration code (read from UserDefaults, write to keychain, delete from UserDefaults, handle partial migration). That migration itself becomes a security surface — the token exists in both locations during the transition. The "security sprint" never happens because there's always a higher-priority feature. Meanwhile, the token is in plaintext in the app's plist, included in every iCloud backup.

Correct action: Use the safe add-or-update pattern from this skill. It's 15 lines of code. The SecItem call itself is not meaningfully harder than UserDefaults — the perceived complexity comes from not understanding the model.

Push-back template: "The keychain call is 15 lines, same as UserDefaults. Doing it in UserDefaults now means writing migration code later — which is actually harder. Let me write it correctly the first time."

Scenario 2: "Delete the keychain item when we get an error"

Context: Background refresh fails intermittently with errSecInteractionNotAllowed. The quick fix: delete the "corrupted" token and force re-login.

Pressure: "Users are complaining about stale data. Just clear the token and re-auth on next launch."

Reality: The token is not corrupted. The device is locked and kSecAttrAccessibleWhenUnlocked prevents access. Deleting it forces every user to re-authenticate after any background failure — which is every night when their phone locks. The actual fix is changing the accessibility level to kSecAttrAccessibleAfterFirstUnlock, which takes one line.

Correct action: Change the item's accessibility to kSecAttrAccessibleAfterFirstUnlock. For existing items already stored with the wrong level, add a one-time migration on app launch (read, delete, re-add with correct accessibility).

Push-back template: "The token isn't corrupted — the device is locked. Deleting it forces every user to re-login every morning. The fix is one line: change the accessibility class to AfterFirstUnlock. I can also add a migration for existing users."

Scenario 3: "Use this keychain wrapper library, everyone uses it"

Context: Team is integrating a popular open-source keychain wrapper to "simplify" keychain access.

Pressure: "It has 5,000 GitHub stars and handles all the edge cases."

Reality: Quinn documents this pattern explicitly: most keychain issues reported on Apple Developer Forums trace back to wrapper libraries, not the keychain itself. Wrappers often hardcode kSecMatchLimit, assume return types, conflate accessibility with access control, or use delete-then-add instead of update. When the wrapper breaks, you debug both the wrapper's abstraction AND the underlying SecItem call. You also inherit the wrapper's opinion about access groups, accessibility, and error handling — which may not match your requirements.

Correct action: Write a thin extension or function specific to your app's needs. The safe add-or-update pattern, a read function, and a delete function cover 95% of use cases in under 50 lines.

Push-back template: "Most keychain bugs on Apple's forums come from wrapper libraries, not the keychain itself. Our needs are 3 functions — save, read, delete. That's 50 lines of code we fully understand, versus a dependency that makes its own decisions about access groups and error handling."

Checklist

Before shipping keychain code:

Model:

  • Using SecItem functions directly (not a wrapper you don't understand)
  • All queries include ALL primary key attributes (service + account for generic passwords)
  • Using update-then-add pattern, not delete-then-add
  • kSecMatchLimit explicitly set where needed (never relying on defaults)

Data Protection:

  • kSecAttrAccessible set explicitly on every add operation
  • Background-accessed items use AfterFirstUnlock (not WhenUnlocked)
  • errSecInteractionNotAllowed handled without deleting the item
  • Tested on a locked physical device (not just Simulator)

Access Control:

  • Biometric flag matches security requirement (currentSet vs any)
  • LAContext reuse duration is appropriate (not excessively long)
  • Graceful fallback if biometry is unavailable or fails

Sharing:

  • Keychain access group entitlement matches code (including Team ID prefix)
  • All sharing targets have the same access group in their entitlements
  • Access group specified explicitly in queries (not relying on default)

Mac Compatibility (if multiplatform):

  • kSecUseDataProtectionKeychain set to true on all macOS operations
  • Tested on macOS (not just iOS)

Error Handling:

  • Every SecItem call checks the OSStatus return value
  • errSecDuplicateItem handled (not swallowed or logged-and-ignored)
  • errSecItemNotFound handled as a normal case (not an error in read flows)
  • Error context includes service, account, and operation attempted

Resources

WWDC: 2019-709

Docs: /security/keychain_services, /security/certificate_key_and_trust_services, /technotes/tn3137-on-mac-keychains

Apple Forums: thread/724023 (SecItem Fundamentals), thread/724013 (SecItem Pitfalls)

Skills: axiom-keychain-diag, axiom-keychain-ref, axiom-cryptokit, axiom-code-signing, axiom-app-attest

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.35%
按下载量换算110

Claude

30.61%
按下载量换算92

Cursor

20.66%
按下载量换算62

Gemini CLI

9.72%
按下载量换算29

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills