Repository navigation
TrustKit 4.0 - #378
Open
alexanderdibenedetto wants to merge 10 commits into
Open
TrustKit 4.0#378alexanderdibenedetto wants to merge 10 commits into
alexanderdibenedetto wants to merge 10 commits into
Conversation
…de 27; Drop Cocoapods support; Add visionOS support (#366) * Remove TrustKit_Static product * Apply hardening settings. * Update min versions to align to Xcode 27 building. * Remove custom settings; align min versions; align C/C++ versions. * Remove target build settings duplicated at the project level * Update license text to latest MIT template and update year. * Build CI and releases with Xcode 27; move OCMock to SPM Drop project-level staticlib and LTO, disable pointer auth in Debug, pin OCMock by commit, and remove the vendored OCMock references. * Use SPM for the demo project and remove CocoaPods Reference the repo root as a local Swift package, delete the Podfile, Pods and workspace, and raise the demo's iOS deployment target to 15.0. * Drop CocoaPods; make <TrustKit/TrustKit.h> work through SPM Move the public headers into public/TrustKit/ so SPM consumers can use the framework-style import, and check it in validate_swift_package.sh. Remove the podspec, and update the README and getting-started guide. * Set minimums to Xcode 27's floors; fix demo launch on iOS 27 Lower tvOS to 15 and declare iOS 15, macOS 12, tvOS 15 and watchOS 9 in Package.swift (tools 5.7) and the README. Drop availability checks and deprecated Security fallbacks that the new minimums make dead, adopt the UIScene lifecycle in both demos, and remove the stale circle.yml reference. * Add visionOS support, watchOS tests and demo UI tests Add visionOS framework and test targets (visionOS 1.0), include visionOS in Package.swift, the XCFramework, CI and pin failure reports, and run the unit test suite on watchOS. Give both demos good-pin, bad-pin and unpinned buttons with UI tests run in a new CI job, and evaluate trust off the main thread. * Remove the stale TrustKit_Static scheme * Make CI run on every PR. * Set UI Tests team to DT. * Download missing simulator runtime if needed; fixes watchos-simulator tests. * Support Mac Catalyst and report Catalyst and iOS-on-Mac separately Enable Mac Catalyst on the iOS framework and test targets, declare it in Package.swift, and add it to CI, the XCFramework and package validation. Pin failure reports now send MAC_CATALYST and IOS_ON_MAC. * Enable module verifier for all C/C++ emitted and supported versions of TrustKit. * Verify the module as Objective-C++ too (TrustKit.xcodeproj/project.pbxproj) Stop demo UI test failures from hanging CI and report the alert contents (scripts/run_demo_ui_tests.sh, TrustKitDemo/TrustKitDemoUITests/TrustKitDemoUITests.swift) * Add the simulator runtime image directly when the device is unavailable * Install the watchOS simulator runtime explicitly on CI Replace the runtime check in the test scripts with an install step that runs before the watchOS tests: warm up CoreSimulator, export the runtime image and add it with simctl. * Reinstall the watchOS runtime on CI only when the simulator is unusable Always warm up CoreSimulator. If the simulator still isn't available, replace the registered runtime image with a fresh export, since adding a second copy is rejected as a duplicate. --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
* Finish the 4.0 cleanup and add a WKWebView pinning example Move both Xcode projects to the current file format (objectVersion 77) and apply Xcode 27's recommended settings to the demo project. Mark the two macOS-only symbols API_UNAVAILABLE instead of NS_AVAILABLE_MAC(10_9), drop the always-true OS version check in the reporter, and remove or correct comments that described code paths for OS versions TrustKit no longer supports. Replace the UIWebView section of the getting started guide with a WKWebView example that validates off the main thread, and add that example to both demos with UI tests for a pinned page that loads and one that is blocked. * Only report Blocked in the demo web views when TrustKit blocked the load Record the host whenever TrustKit cancels a challenge and show Blocked only for failed navigations to that host, naming the failing URL. Other cancelled navigations, such as an interrupted page load, no longer show an alert. --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
* Replace TSKLog and +setLoggerBlock: with os_log (#128) TrustKit now logs through os_log under the com.datatheorem.trustkit subsystem and the TrustKit category. Pin validation failures and other errors use the error level, successful validations info, and per-step details debug. Pinned hostnames are logged as public data, and pins are logged in base64 to match the configuration format. +[TrustKit setLoggerBlock:] is removed; use pinningValidatorCallback to handle validation results in code. Release builds now emit logs. * Log nil-delegate NSURLSession creation at debug level * Keep the logged configuration private and poll the log store in TSKLoggerTests Report URIs can carry credentials or tokens, so the configuration dump uses os_log's default private redaction. Log entries reach OSLogStore asynchronously, so the test waits for the pin failure entry instead of querying once. * Check simulator availability with xcodebuild before skipping the runtime repair simctl can list the watchOS simulator as available while xcodebuild sees its runtime as (null), so the repair was skipped and the tests failed. * Query the log store off the main thread in TSKLoggerTests A blocked OSLogStore query on the main thread also blocked the test's timeout. Polling on a background queue and waiting on a semaphore keeps the 30-second limit, and a late result after a timeout is harmless. --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
#341) (#371) * Drop watchOS from the CI test matrix until actions/runner-images#14946 is fixed * Allow any domain name or IP address in the pinning configuration (#333, #341) Removes the bundled public suffix list. Keys are validated by shape, IP addresses are canonicalized with inet_pton/inet_ntop, and includeSubdomains uses plain suffix matching. * Allow repeated pin validation callbacks in end-to-end tests --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
* Hash each certificate's SPKI as encoded instead of rebuilding it (#236) Read the Subject Public Key Info straight from the certificate's DER and hash it as is. This removes the five hardcoded ASN.1 headers and the extra trust evaluation per certificate on a cache miss, so any key type can be pinned. Adds a P-521 test certificate and malformed-input tests for the DER reader. * Stop building arm64e and arm64e.x1 simulator slices No simulator runtime can run them (all are arm64-only), and Xcode 27 ships no Swift standard library for them. Device, macOS and Mac Catalyst slices keep arm64e and arm64e.x1. * Read the certificate's SPKI in Swift (#236) First Swift code in TrustKit. The DER reader moves to TrustKit/Swift/SubjectPublicKeyInfo.swift, exposed to Objective-C as TSKSubjectPublicKeyInfo. Xcode compiles it into the framework targets; SwiftPM builds it as a TrustKitSwift target. Uses Swift 6 language mode and swift-tools-version 6.0. Removes the recursive HEADER_SEARCH_PATHS, which resolved <TrustKit/…> to source headers and broke the framework module. Documents the empty Swift file that Objective-C-only apps using the static XCFramework need below iOS 16 / macOS 13. * Replace the Python helper scripts get_pin_from_certificate.sh replaces get_pin_from_certificate.py. It hashes any key type and reads PEM or DER, including with macOS's built-in LibreSSL. Removes generate_test_certificates.py; the test certificates are committed and nothing regenerates them. * Hash the SPKI as encoded in the pin script; version the SPKI cache openssl pkey re-encodes the key, so for some certificates the script's pin never matched what TrustKit computes. The script now hashes the SPKI bytes straight from the certificate. The shared SPKI cache file is renamed so that hashes cached by TrustKit 3.x are recomputed. --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
* Import what TSKPinningValidator_Private.h uses * Add SwiftLint, swift-format and clang-format checks * Apply lint formatting --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
* Skip files deleted from the working tree in lint.sh * Remove the deprecated public key algorithm API kTSKPublicKeyAlgorithms, TSKSupportedAlgorithm and the kTSKAlgorithm* constants have been deprecated since 1.6.0. Configs that still set TSKPublicKeyAlgorithms keep working because the parser ignores unknown keys. Also delete the unused internal TSKPublicKeyAlgorithm.h and rename TSKPublicKeyAlgorithmTests to TSKSPKIHashCacheTests, after the class it tests. --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io>
There was a problem hiding this comment.
Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.
Besides the inline finding, I checked whether SPKI hashes cached by 3.x could be reused after the upgrade, which would block connections pinned with 4.0 pins. They can't: the shared cache identifier in TrustKit/Pinning/TSKSPKIHashCache.h changes from spki-hash.cache to spki-hash-v2.cache, so 4.0 starts with an empty cache.
Extended reasoning...
The release changes SPKI hashing from rebuilding the key with per-algorithm ASN.1 headers to hashing the SPKI exactly as encoded. Because the base branch's cache file name differs from this one, old cache entries are never loaded.
EthanArbuckle
previously approved these changes
Oct 26, 2026
NSExceptional
previously approved these changes
Oct 26, 2026
* Reject malformed expiration dates, report user-anchor failures on macOS, fix the exclude-subdomain key, and stop skipping TSK-prefixed delegates * Remove the watchOS runtime workaround, correct the report ID docs, and refresh the Info.plist screenshot * Update TrustKit/parse_configuration.m Co-authored-by: uroboro <uroboro845@gmail.com> * Fix linting. * Fix apply suggestion from Fede --------- Co-authored-by: Alexander DiBenedetto <adb@datatheorem.io> Co-authored-by: uroboro <uroboro845@gmail.com>
alexanderdibenedetto
dismissed stale reviews from NSExceptional and EthanArbuckle
via
October 28, 2026 22:32
6804d73
alexanderdibenedetto
requested review from
EthanArbuckle,
NSExceptional and
uroboro
October 28, 2026 22:35
EthanArbuckle
approved these changes
Oct 28, 2026
uroboro
approved these changes
Nov 2, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TrustKit 4.0 is a major release. It raises the minimum OS versions, drops CocoaPods, adds visionOS, logs through
os_log, and accepts any domain name or IP address in the pinning configuration. Some of these changes affect which connections get pinned, so test this beta before you ship it. Please report problems in Issues.Breaking changes
Requirements
swift-tools-version:6.0). So does building from the Xcode project, which now uses the Xcode 16 project format. TrustKit itself is built and tested with Xcode 27.TrustKit-static.zip) attached to each release.TrustKit_StaticXcode target is removed. UseTrustKit-static.zipinstead.Removed APIs
+[TrustKit setLoggerBlock:]is removed. TrustKit now logs throughos_log(see Logging). To act on validation results in code, setpinningValidatorCallback.kTSKPublicKeyAlgorithms,TSKSupportedAlgorithm,kTSKAlgorithmRsa2048,kTSKAlgorithmRsa4096,kTSKAlgorithmEcDsaSecp256r1andkTSKAlgorithmEcDsaSecp384r1are removed. They have been deprecated since 1.6.0, so remove them from your code. A configuration or Info.plist that still setsTSKPublicKeyAlgorithmskeeps working, because the key is ignored.macOS-only symbols no longer compile on other platforms
kTSKIgnorePinningForUserDefinedTrustAnchorsandTSKTrustEvaluationFailedUserDefinedTrustAnchorare now marked unavailable on iOS, Mac Catalyst, tvOS, watchOS and visionOS. Using them there is a compile error. In code shared across platforms, wrap them in#if TARGET_OS_OSX(Objective-C) or#if os(macOS)(Swift).Header location
The public headers moved to
TrustKit/public/TrustKit/.#import <TrustKit/TrustKit.h>and@import TrustKit;now work the same way with Swift Package Manager and with the framework. If you have header search paths pointing into a TrustKit checkout, update them.Static XCFramework in apps without Swift
Part of TrustKit is now written in Swift. This is internal only, and the public API hasn't changed. If your app has no Swift code of its own and targets an OS earlier than iOS 16, tvOS 16, Mac Catalyst 16 or macOS 13, linking the XCFramework fails with
Undefined symbols … __swift_FORCE_LOAD_$_swiftCompatibility56. To fix it, add an empty Swift file to your app target.Swift contributions
Starting with 4.0, TrustKit accepts contributions in Swift. This release ships TrustKit's first Swift code. Over time we plan to move the Objective-C classes to Swift that Objective-C can still call, so existing apps keep working unchanged.
TrustKit/Swift/and add them to each framework target inTrustKit.xcodeproj.scripts/lint.shruns swift-format and SwiftLint, and CI fails if lint fails.Pinning configuration (#333, #341)
These changes affect which connections are pinned, so review your configuration when you upgrade.
api.internalorlocalhost, and IPv4 or IPv6 addresses. 3.x rejected names that didn't end in an entry of its bundled public suffix list. That list is now removed.*.example.com, or any key containing:,/,@or a space. 3.x loaded these keys, and the domain silently stayed unpinned. Like any other configuration error, this raises anNSExceptionfrominitSharedInstanceWithConfiguration:. If your app downloads its configuration at runtime, validate it before you pass it to TrustKit.API.example.comnever matched, and the host stayed unpinned without any warning. In 4.0 that key matches and the host is pinned.kTSKIncludeSubdomainsnow uses plain suffix matching. It throws for an IP address or a single-label domain such ascom. Otherwise it is allowed on any domain, including public suffixes such asco.ukorappspot.com, which 3.x rejected.Any key type can be pinned
TrustKit now hashes each certificate's Subject Public Key Info exactly as it is encoded in the certificate. Before, it rebuilt the Subject Public Key Info, and that only worked for a fixed list of key types.
TSKTrustEvaluationErrorCouldNotGenerateSpkiHash, and the connection was blocked.get_pin_from_certificate.shreplaces the Python script. It computes pins the same way TrustKit does, and takes a PEM or DER file:./get_pin_from_certificate.sh ca.pem. Don't re-encode the key first, for example withopenssl pkey. For some certificates that changes the bytes, and the pin won't match.Logging
TrustKit logs through the unified logging system (#128), under the subsystem
com.datatheorem.trustkitand the categoryTrustKit.log stream --level debug --predicate 'subsystem == "com.datatheorem.trustkit"'. For the simulator, putxcrun simctl spawn bootedin front of it.Pin failure reports
The
app-platformfield now reportsVISIONOSfor visionOS apps,MAC_CATALYSTfor Mac Catalyst apps, andIOS_ON_MACfor iPhone or iPad apps running on a Mac. 3.x reported the last two asIOS. If your report server filters on this field, update it. The other report fields haven't changed.New platforms
Package.swift, tested in CI and has its own slice in the XCFramework.arm64eslices.Docs and demos
UIWebViewsection is replaced by aWKWebViewexample in Objective-C and Swift. The example validates off the main thread, and both demo apps include it.For contributors
scripts/lint.shruns swift-format, SwiftLint and clang-format, and CI fails when lint fails.What's Changed
Full Changelog: 3.0.8...4.0.0-beta.1