Certificate pinning disabled in Swift TrustKit settings

Certificate pinning disabled in Swift TrustKit settings

Description

For a domain that requires certificate pinning, kTSKEnforcePinning: false does not block pin mismatches, so the intended additional protection is not enforced. Report-only mode can be useful during a rollout, but enforcement should match your requirements once validation is complete. Pinning is separate from basic TLS trust validation; server certificates must be validated regardless of whether pinning is enforced.

On macOS, setting kTSKIgnorePinningForUserDefinedTrustAnchors to true skips pin validation for certificate chains ending in a user-defined trust anchor. Check that this exception matches your organization's certificate policy.

Potential impact

  • Bypass of certificate pinning.
  • Server impersonation using a certificate that pinning was intended to block.
  • Exposure of sensitive network traffic when an attacker controls the communication path and has the necessary certificate.

Remediation

  1. Validate the configuration and deployment for domains that require pinning, then set kTSKEnforcePinning: true.
  2. If network delegate swizzling is disabled, call TrustKit's TSKPinningValidator directly from authentication challenge handling.
  3. On macOS, set kTSKIgnorePinningForUserDefinedTrustAnchors: false if pinning must also apply to user-defined trust anchors. Check compatibility with intended trust policies, such as those used by organizational proxies.

Examples

These partial examples compare pin enforcement settings. A working configuration also needs the pin list, TrustKit initialization, and integration with network authentication challenge handling.

Before

swift
let config = [
    kTSKPinnedDomains: [
        "api.example.com": [kTSKEnforcePinning: false]
    ]
]

After

swift
import TrustKit

private enum BuildEmbeddedPins {
    // 실제 배포에서는 빌드 시 생성한 서버 SPKI SHA-256 pin으로 교체합니다.
    static let primary = "HXXQgxueCIU5TTLHob/bPbwcKOKw6DkfsTWYHbxbqTY="
    static let backup = "0SDf3cRToyZJaMsoS17oF72VMavLxj/N7WBNasNuiR8="
}

func makeTrustKitConfiguration() -> [String: Any] {
    return [
        kTSKPinnedDomains: [
            "api.example.com": [
                kTSKEnforcePinning: true,
                kTSKPublicKeyHashes: [
                    BuildEmbeddedPins.primary,
                    BuildEmbeddedPins.backup
                ]
            ] as [String: Any]
        ]
    ]
}

Explanation:

  • Before: Pinning violations are not forcibly blocked.
  • After: Pinning is enforced for the target domain. The current key and a separately provisioned backup SPKI pin support certificate rotation. Replace the example values with your server's actual pins, and embed both pins in the signed application build rather than obtaining them from remote or user input.

References