v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
MEDIUM AI PREVALENCE: MEDIUM auth.swift.keychain.insecure-accessible

A Keychain item is created with kSecAttrAccessibleAlways (or kSecAttrAccessibleAlwaysThisDeviceOnly).

Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.

Why this matters

"Always" accessibility means the item is readable even while the device is locked, widening the window in which a lost or seized device can leak the stored credential; both constants are deprecated by Apple for exactly this reason (CWE-311). AI-generated Keychain snippets often pick "Always" as the most permissive option so the sample never fails to read.

Use the most restrictive class that still works for your access pattern, e.g. kSecAttrAccessibleWhenUnlockedThisDeviceOnly, so the item is available only while the device is unlocked and never syncs off-device.

VULNERABLE
vulnerable.swift
import Security

func storeToken(_ data: Data) {
    // ruleid: auth.swift.keychain.insecure-accessible
    let query1: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccessible as String: kSecAttrAccessibleAlways,
        kSecValueData as String: data,
    ]
    SecItemAdd(query1 as CFDictionary, nil)

    // ruleid: auth.swift.keychain.insecure-accessible
    let query2: [String: Any] = [
        kSecAttrAccessible as String: kSecAttrAccessibleAlwaysThisDeviceOnly,
        kSecValueData as String: data,
    ]
    SecItemAdd(query2 as CFDictionary, nil)
}
SAFE
safe.swift
import Security

func storeToken(_ data: Data) {
    // Restrictive accessibility: only when unlocked, never off-device.
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
        kSecValueData as String: data,
    ]
    SecItemAdd(query as CFDictionary, nil)
}

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.swift.keychain.insecure-accessible -- <reason>

References

https://developer.apple.com/documentation/security/ksecattraccessiblewhenunlockedthisdeviceonly ↗https://cwe.mitre.org/data/definitions/311.html ↗