Use current time by default during validation in RFC5280Policy and OCSPPolicy - #266
Merged
Merged
Conversation
…dation* and used as the validation time in `RFC5280Policy` and `OCSPPolicy`.
RFC5280Policy and OCSPPolicy.RFC5280Policy and OCSPPolicy.
simonjbeaumont
approved these changes
Jul 15, 2025
simonjbeaumont
left a comment
Contributor
There was a problem hiding this comment.
This LGTM—nice work 👏
RFC5280Policy and OCSPPolicy.
aryan-25
added a commit
to aryan-25/swift-certificates
that referenced
this pull request
Oct 8, 2025
New initializers for `ExpiryPolicy`, `RFC5280Policy`, and `OCSPVerifierPolicy` were introduced in apple#266. These initializers were added to prevent users from specifying `Date.now` as the time to validate certificate expiry against. For context, the problem was that `Date.now` would be evaluated at initialization, but validation could occur at a later stage, at which point the validation time would become stale. These initializers had a `fixedValidationTime: Date? = nil` argument, where a non-`nil` value denoted a *fixed* time to validate against, and a `nil` value denoted that the current time, evaluated at the point of validation, would be used for validation (the common case). Although the dangers of specifying `fixedValidationTime = .now` were documented, in practice, it is very easy for users to miss this and continue using the API in an incorrect way. Given that most users will validate certificate expiry against the current time, we want to default to this and remove the validation time argument from the public initializers entirely. Users who want to specify a fixed predetermined time must explicitly opt-in by using `@_spi(FixedValidationTime)` to access the initializers that have a *non-optional* `fixedValidationTime` argument. Modifications: - Deprecated the initializers of `RFC5280Policy` and `OCSPVerifierPolicy` and introduced two new initializers for each: one without a validation time argument (common case), and one with a *non-optional* validation time argument backed behind an SPI - Updated the initializers of `ExpiryPolicy` (an internal type) - Additional changes: - Updated test cases to use new initializers - Updated examples in documentation to use new initializers Result: `RFC5280Policy` and `OCSPVerifierPolicy` can be used more safely
Lukasa
pushed a commit
that referenced
this pull request
Oct 13, 2025
### Motivation: New initializers for `ExpiryPolicy`, `RFC5280Policy`, and `OCSPVerifierPolicy` were introduced in #266. These initializers were added to prevent users from specifying `Date.now` as the time to validate certificate expiry against. For context, the problem was that `Date.now` would be evaluated at initialization, but validation could occur at a later stage, at which point the validation time would become stale. These initializers had a `fixedValidationTime: Date? = nil` argument, where a non-`nil` value denoted a *fixed* time to validate against, and a `nil` value denoted that the current time, evaluated at the point of validation, would be used for validation (the common case). Although the dangers of specifying `fixedValidationTime = .now` were documented, in practice, it is very easy for users to miss this and continue using the API in an incorrect way. Given that most users will validate certificate expiry against the current time, we want to default to this and remove the validation time argument from the public initializers entirely. Users who want to specify a fixed predetermined time **must explicitly opt-in** by using `@_spi(FixedExpiryValidationTime)` to access the initializers that have a *non-optional* `fixedExpiryValidationTime` argument. ### Modifications: - Deprecated the initializers of `RFC5280Policy` and `OCSPVerifierPolicy` and introduced two new initializers for each: one without a validation time argument (common case), and one with a *non-optional* validation time argument guarded behind an SPI - Updated the initializers of `ExpiryPolicy` (an internal type) - Additional changes: - Updated test cases to use new initializers - Updated examples in documentation to use new initializers ### Result: `RFC5280Policy` and `OCSPVerifierPolicy` can be used more safely
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.
Motivation:
The initializers of
RFC5280PolicyandOCSPPolicyrequire a validation time as an argument. If this argument is set toDate.now, the timestamp would be captured at the point of initialization. As such, if the validation method is invoked on the policy instance long after initialization, the timestamp can become stale at that point. This means that the validation function could incorrectly determine a certificate (RFC5280Policy) or an OCSP response (OCSPPolicy) to be valid, when it has actually expired by the time the validation is performed.This is not an issue in common use-cases where the policy is initialized (with
validationTimeset to.now) inside aPolicyBuilderclosure, because the closure is evaluated at the point of validation. However, some use-cases may initialize the policy independently; the issue can potentially arise here.Modifications:
This patch deprecates the current initializers of
RFC5280PolicyandOCSPPolicyto guide users toward using a safer initializer which requires afixedValidationTime: Date?argument:nil(default) will lead to the current time being obtained at the point of validation. This will prevent the bug described above.Dateinstance preserves the ability to validate against a fixed point in time, i.e. a time in the past or future, but not the current time.Result:
Users now have the option to use a safer initializer to construct
RFC5280PolicyandOCSPPolicy.