From 8ca9b794991cd0c2397c34f9c965549d9de507e9 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Thu, 13 Nov 2025 16:08:47 -0800 Subject: [PATCH 01/50] added file for thirdpartypayment, added file to toc under new extensions topic --- .../application-fido2/thirdpartypayment.md | 20 +++++++++++++++++++ docs/users-manual/toc.yml | 8 ++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 docs/users-manual/application-fido2/thirdpartypayment.md diff --git a/docs/users-manual/application-fido2/thirdpartypayment.md b/docs/users-manual/application-fido2/thirdpartypayment.md new file mode 100644 index 000000000..2f60152d5 --- /dev/null +++ b/docs/users-manual/application-fido2/thirdpartypayment.md @@ -0,0 +1,20 @@ +--- +uid: Fido2ThirdPartyPayment +--- + + + +# Third-party payment extension (thirdPartyPayment) + diff --git a/docs/users-manual/toc.yml b/docs/users-manual/toc.yml index cc5121b29..fc898612c 100644 --- a/docs/users-manual/toc.yml +++ b/docs/users-manual/toc.yml @@ -337,8 +337,12 @@ href: application-fido2/cred-blobs.md - name: Large blobs href: application-fido2/large-blobs.md - - name: HMAC secret extension - href: application-fido2/hmac-secret.md + - name: Extensions + items: + - name: HMAC secret extension + href: application-fido2/hmac-secret.md + - name: Third-party payment extension + href: application-fido2/thirdpartypayment.md - name: Commands items: - name: FIDO2 commands From 9bc123ac64750aa1f4eea1bbbbca3a6c19219ded Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Thu, 13 Nov 2025 17:03:44 -0800 Subject: [PATCH 02/50] makecredential code sample --- .../application-fido2/thirdpartypayment.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/users-manual/application-fido2/thirdpartypayment.md b/docs/users-manual/application-fido2/thirdpartypayment.md index 2f60152d5..3a0715b55 100644 --- a/docs/users-manual/application-fido2/thirdpartypayment.md +++ b/docs/users-manual/application-fido2/thirdpartypayment.md @@ -18,3 +18,28 @@ limitations under the License. --> # Third-party payment extension (thirdPartyPayment) + + +## Creating a thirdPartyPayment-enabled credential + +```C# +using (Fido2Session fido2Session = new Fido2Session(yubiKey)) +{ + // Your app's key collector, which will be used to perform PIN/UV verification during MakeCredential() + fido2Session.KeyCollector = SomeKeyCollectorDelegate; + + // Create the parameters for MakeCredential (relyingParty and userEntity set elsewhere) + var makeCredentialParameters = new MakeCredentialParameters(relyingParty, userEntity); + + // Add the thirdPartyPayment extension + makeCredentialParameters.AddThirdPartyPaymentExtension(); + + // Add the "rk" option to make the credential discoverable + makeCredentialParameters.AddOption(AuthenticatorOptions.rk, true); + + // Create the thirdPartyPayment-enabled credential using the parameters set above + MakeCredentialData credentialData = fido2Session.MakeCredential(makeCredentialParameters); +} +``` + +## Authenticating a third-party payment transaction \ No newline at end of file From eb705f87b0f78bc3b00d2554e2d91e6eecd39fb3 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Thu, 20 Nov 2025 16:30:22 -0800 Subject: [PATCH 03/50] more sample code --- .../application-fido2/thirdpartypayment.md | 70 ++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/docs/users-manual/application-fido2/thirdpartypayment.md b/docs/users-manual/application-fido2/thirdpartypayment.md index 3a0715b55..af7964cc9 100644 --- a/docs/users-manual/application-fido2/thirdpartypayment.md +++ b/docs/users-manual/application-fido2/thirdpartypayment.md @@ -18,28 +18,82 @@ limitations under the License. --> # Third-party payment extension (thirdPartyPayment) +To verify that a YubiKey supports the thirdPartyPayment extension, check the key's ``AuthenticatorInfo``: +```C# +using (Fido2Session fido2Session = new Fido2Session(yubiKey)) +{ + if (fido2Session.AuthenticatorInfo.Extensions.Contains("thirdPartyPayment")) + { + ... + } +} +``` ## Creating a thirdPartyPayment-enabled credential ```C# using (Fido2Session fido2Session = new Fido2Session(yubiKey)) { - // Your app's key collector, which will be used to perform PIN/UV verification during MakeCredential() + // Your app's key collector, which will be used to check user presence and perform PIN/UV + // verification during MakeCredential(). fido2Session.KeyCollector = SomeKeyCollectorDelegate; - // Create the parameters for MakeCredential (relyingParty and userEntity set elsewhere) - var makeCredentialParameters = new MakeCredentialParameters(relyingParty, userEntity); + // Create the parameters for MakeCredential (relyingParty, userEntity, and clientDataHashValue + // set elsewhere). + var makeCredentialParameters = new MakeCredentialParameters(relyingParty, userEntity) + { + ClientDataHash = clientDataHashValue - // Add the thirdPartyPayment extension - makeCredentialParameters.AddThirdPartyPaymentExtension(); + }; - // Add the "rk" option to make the credential discoverable + // Add the thirdPartyPayment extension plus the "rk" option (to make the credential discoverable). + makeCredentialParameters.AddThirdPartyPaymentExtension(); makeCredentialParameters.AddOption(AuthenticatorOptions.rk, true); - // Create the thirdPartyPayment-enabled credential using the parameters set above + // Create the third-party payment enabled credential using the parameters set above. MakeCredentialData credentialData = fido2Session.MakeCredential(makeCredentialParameters); } ``` -## Authenticating a third-party payment transaction \ No newline at end of file +After calling ``MakeCredential()``, we can check the ``AuthenticatorData`` to verify that the credential was successfully created with the thirdPartyPayment extension enabled: + +```C# +using (Fido2Session fido2Session = new Fido2Session(yubiKey)) +{ + ... + // Returns true if the extension was enabled. + bool thirdPartyPaymentStatus = credentialData.AuthenticatorData.GetThirdPartyPaymentExtension(); +} +``` + +## Authenticating a third-party payment transaction + +```C# +using (Fido2Session fido2Session = new Fido2Session(yubiKey)) +{ + // Your app's key collector, which will be used to check user presence and perform PIN/UV + // verification during GetAssertion(). + fido2Session.KeyCollector = SomeKeyCollectorDelegate; + + // Create the parameters for GetAssertion (relyingParty and clientDataHashValue set elsewhere), + // and add the request for the thirdPartyPayment return value to the parameters. + var getAssertionParameters = new GetAssertionParameters(relyingParty, clientDataHashValue); + getAssertionParameters.RequestThirdPartyPayment(); + + // Get the assertion using the parameters set above. + IReadOnlyList assertionDataList = fido2Session.GetAssertions(getAssertionParameters); +} +``` + +After calling ``GetAssertions()``, we can check the state of the ThirdPartyPayment return value via the ``AuthenticatorData``: + +```C# +using (Fido2Session fido2Session = new Fido2Session(yubiKey)) +{ + ... + // If the YubiKey contains multiple credentials for the relyingParty, this returns the value + // from the first credential's data. True = third-party payment enabled. + bool thirdPartyPaymentValue = assertionDataList[0].AuthenticatorData.GetThirdPartyPaymentExtension(); +} +``` \ No newline at end of file From 150b96c46c37857009ccee6a6b2a06b11f863bcb Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Fri, 21 Nov 2025 12:41:27 -0800 Subject: [PATCH 04/50] getassertion docs --- .../application-fido2/thirdpartypayment.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/users-manual/application-fido2/thirdpartypayment.md b/docs/users-manual/application-fido2/thirdpartypayment.md index af7964cc9..b885cee9f 100644 --- a/docs/users-manual/application-fido2/thirdpartypayment.md +++ b/docs/users-manual/application-fido2/thirdpartypayment.md @@ -69,6 +69,17 @@ using (Fido2Session fido2Session = new Fido2Session(yubiKey)) ## Authenticating a third-party payment transaction +To successfully authenticate a third-party payment transaction using a YubiKey, the following must occur: + +- The YubiKey credential used for ``GetAssertion`` must be [third-party payment enabled](#creating-a-thirdpartypayment-enabled-credential). +- The thirdPartyPayment extension must be added to the parameters for ``GetAssertion``. + +During ``GetAssertion``, the YubiKey will return a boolean value for the thirdPartyPayment extension. If both requirements have been met, the value returned will be ``true``. + +### GetAssertion example with thirdPartyPayment + +To get an assertion with thirdPartyPayment, do the following: + ```C# using (Fido2Session fido2Session = new Fido2Session(yubiKey)) { From 18ff7f6135ed1696f92bfdd3f11f0a3c25e60cdd Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Fri, 21 Nov 2025 14:54:00 -0800 Subject: [PATCH 05/50] makecredential docs --- .../application-fido2/thirdpartypayment.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/users-manual/application-fido2/thirdpartypayment.md b/docs/users-manual/application-fido2/thirdpartypayment.md index b885cee9f..bae2dce6c 100644 --- a/docs/users-manual/application-fido2/thirdpartypayment.md +++ b/docs/users-manual/application-fido2/thirdpartypayment.md @@ -18,7 +18,13 @@ limitations under the License. --> # Third-party payment extension (thirdPartyPayment) -To verify that a YubiKey supports the thirdPartyPayment extension, check the key's ``AuthenticatorInfo``: + + +## Creating a thirdPartyPayment-enabled credential + +YubiKey credentials can only be used for a third-party payment transaction if the credential itself is thirdPartyPayment-enabled, and enablement must occur when the credential is first created. Enablement simply means that the credential's thirdPartyPayment bit flag has been set to ``true``. + +Only YubiKeys with firmware version 5.8 and higher support the thirdPartyPayment extension. To verify whether a particular YubiKey supports the feature, check the key's ``AuthenticatorInfo``: ```C# using (Fido2Session fido2Session = new Fido2Session(yubiKey)) @@ -30,7 +36,9 @@ using (Fido2Session fido2Session = new Fido2Session(yubiKey)) } ``` -## Creating a thirdPartyPayment-enabled credential +### MakeCredential example with thirdPartyPayment + +To create a thirdPartyPayment-enabled credential, we must add the thirdPartyPayment extension to the parameters for ``MakeCredential()``: ```C# using (Fido2Session fido2Session = new Fido2Session(yubiKey)) @@ -56,7 +64,7 @@ using (Fido2Session fido2Session = new Fido2Session(yubiKey)) } ``` -After calling ``MakeCredential()``, we can check the ``AuthenticatorData`` to verify that the credential was successfully created with the thirdPartyPayment extension enabled: +After calling ``MakeCredential()``, we can check the ``AuthenticatorData`` to verify extension enablement: ```C# using (Fido2Session fido2Session = new Fido2Session(yubiKey)) From c7d9118135dea66b63970d60c9ec43f69f49c569 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Fri, 21 Nov 2025 16:22:52 -0800 Subject: [PATCH 06/50] third party payment overview --- docs/users-manual/application-fido2/thirdpartypayment.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/users-manual/application-fido2/thirdpartypayment.md b/docs/users-manual/application-fido2/thirdpartypayment.md index bae2dce6c..235c94c29 100644 --- a/docs/users-manual/application-fido2/thirdpartypayment.md +++ b/docs/users-manual/application-fido2/thirdpartypayment.md @@ -18,13 +18,17 @@ limitations under the License. --> # Third-party payment extension (thirdPartyPayment) +CTAP 2.2 and YubiKeys with firmware 5.8+ support the [thirdPartyPayment extension](https://fidoalliance.org/specs/fido-v2.2-ps-20250714/fido-client-to-authenticator-protocol-v2.2-ps-20250714.html#sctn-thirdPartyPayment-extension), which allows credentials to be used for payment authentication scenarios where the transaction initiator is not the relying party. +For example, suppose a user creates a thirdPartyPayment-enabled credential with their bank. The user then purchases an item from an online merchant and pays using their bank account, and the transaction is validated with their bank credential on their YubiKey. + +According to the CTAP 2.2 standard, implementation of the payment authentication flow is up to the platform. See the W3C's [Secure Payment Confirmation (SPC)](https://www.w3.org/TR/secure-payment-confirmation/) for an example of a possible implementation. ## Creating a thirdPartyPayment-enabled credential -YubiKey credentials can only be used for a third-party payment transaction if the credential itself is thirdPartyPayment-enabled, and enablement must occur when the credential is first created. Enablement simply means that the credential's thirdPartyPayment bit flag has been set to ``true``. +YubiKey credentials (discoverable and non-discoverable) can only be used for a third-party payment transaction if the credential itself is thirdPartyPayment-enabled, and enablement must occur when the credential is first created. Enablement simply means that the credential's thirdPartyPayment bit flag has been set to ``true``. -Only YubiKeys with firmware version 5.8 and higher support the thirdPartyPayment extension. To verify whether a particular YubiKey supports the feature, check the key's ``AuthenticatorInfo``: +Only YubiKeys with firmware version 5.8 and later support the thirdPartyPayment extension. To verify whether a particular YubiKey supports the feature, check the key's ``AuthenticatorInfo``: ```C# using (Fido2Session fido2Session = new Fido2Session(yubiKey)) From f09da74e0c845f6e560bff392a77f447c6b4d283 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Fri, 21 Nov 2025 16:42:05 -0800 Subject: [PATCH 07/50] updated release notes --- docs/users-manual/getting-started/whats-new.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/users-manual/getting-started/whats-new.md b/docs/users-manual/getting-started/whats-new.md index 18db3d8cf..1266be6e5 100644 --- a/docs/users-manual/getting-started/whats-new.md +++ b/docs/users-manual/getting-started/whats-new.md @@ -58,9 +58,9 @@ Features: - Support has been added for the following CTAP 2.2 and YubiKey firmware version 5.8 features ([#299](https://github.com/Yubico/Yubico.NET.SDK/pull/299)): - - [Persistent PinUvAuthToken (PPUAT)](xref:Fido2AuthTokens#persistent-pinuvauthtoken-ppuat): The [GetPersistentPinUvAuthToken()](xref:Yubico.YubiKey.Fido2.Fido2Session.GetPersistentPinUvAuthToken) method has been added to retrieve PPUATs for use with read-only FIDO2 credential management operations, including [EnumerateRelyingParties()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateRelyingParties), [EnumerateCredentialsForRelyingParty()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateCredentialsForRelyingParty%28Yubico.YubiKey.Fido2.RelyingParty%29), and [GetCredentialMetadata()](xref:Yubico.YubiKey.Fido2.Fido2Session.GetCredentialMetadata). PPUATs enable applications to list discoverable credentials from YubiKeys without requiring repeated PIN entry. + - Persistent PinUvAuthToken (PPUAT): The SDK now supports the use of [Persistent PinUvAuthTokens (PPUATs)](xref:Fido2AuthTokens#persistent-pinuvauthtoken-ppuat), which are longer-lived auth tokens that can be used for read-only FIDO2 credential management operations, including [EnumerateRelyingParties()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateRelyingParties), [EnumerateCredentialsForRelyingParty()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateCredentialsForRelyingParty%28Yubico.YubiKey.Fido2.RelyingParty%29), and [GetCredentialMetadata()](xref:Yubico.YubiKey.Fido2.Fido2Session.GetCredentialMetadata). PPUATs enable applications to list discoverable credentials from YubiKeys without requiring repeated PIN entry. - - thirdPartyPayment extension: The [GetThirdPartyPaymentExtension](xref:Yubico.YubiKey.Fido2.AuthenticatorData.GetThirdPartyPaymentExtension) method has been added to check for and return the status of the thirdPartyPayment extension. The thirdPartyPayment extension enables YubiKeys to be used for cross-domain credentials without redirects, as required by Secure Payment Confirmation (SPC) workflows. + - thirdPartyPayment extension: The SDK now supports the [thirdPartyPayment extension](xref:Fido2ThirdPartyPayment), with enables YubiKeys to be used for payment authentication scenarios, including Secure Payment Confirmation (SPC) workflows, where the transaction initiator is not the relying party. - hmac-secret-mc extension: [GetHmacSecretExtension](xref:Yubico.YubiKey.Fido2.AuthenticatorData.GetHmacSecretExtension%28Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase%29) now handles both hmac-secret and hmac-secret-mc extensions when extracting and decrypting secrets. The hmac-secret-mc extension enables PRF (Pseudo-Random Function) during [MakeCredential()](xref:Yubico.YubiKey.Fido2.Fido2Session.MakeCredential%28Yubico.YubiKey.Fido2.MakeCredentialParameters%29). From 9e57faacab344c2ec46e5410fb307db81be182b3 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Fri, 21 Nov 2025 16:44:57 -0800 Subject: [PATCH 08/50] fixed typo --- docs/users-manual/getting-started/whats-new.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/users-manual/getting-started/whats-new.md b/docs/users-manual/getting-started/whats-new.md index 1266be6e5..8b94194fb 100644 --- a/docs/users-manual/getting-started/whats-new.md +++ b/docs/users-manual/getting-started/whats-new.md @@ -60,7 +60,7 @@ Features: - Persistent PinUvAuthToken (PPUAT): The SDK now supports the use of [Persistent PinUvAuthTokens (PPUATs)](xref:Fido2AuthTokens#persistent-pinuvauthtoken-ppuat), which are longer-lived auth tokens that can be used for read-only FIDO2 credential management operations, including [EnumerateRelyingParties()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateRelyingParties), [EnumerateCredentialsForRelyingParty()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateCredentialsForRelyingParty%28Yubico.YubiKey.Fido2.RelyingParty%29), and [GetCredentialMetadata()](xref:Yubico.YubiKey.Fido2.Fido2Session.GetCredentialMetadata). PPUATs enable applications to list discoverable credentials from YubiKeys without requiring repeated PIN entry. - - thirdPartyPayment extension: The SDK now supports the [thirdPartyPayment extension](xref:Fido2ThirdPartyPayment), with enables YubiKeys to be used for payment authentication scenarios, including Secure Payment Confirmation (SPC) workflows, where the transaction initiator is not the relying party. + - thirdPartyPayment extension: The SDK now supports the [thirdPartyPayment extension](xref:Fido2ThirdPartyPayment), which enables YubiKeys to be used for payment authentication scenarios, including Secure Payment Confirmation (SPC) workflows, where the transaction initiator is not the relying party. - hmac-secret-mc extension: [GetHmacSecretExtension](xref:Yubico.YubiKey.Fido2.AuthenticatorData.GetHmacSecretExtension%28Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase%29) now handles both hmac-secret and hmac-secret-mc extensions when extracting and decrypting secrets. The hmac-secret-mc extension enables PRF (Pseudo-Random Function) during [MakeCredential()](xref:Yubico.YubiKey.Fido2.Fido2Session.MakeCredential%28Yubico.YubiKey.Fido2.MakeCredentialParameters%29). From fdb22e9516b6d5b8f3efd51336d67b173117306d Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Tue, 25 Nov 2025 13:04:39 -0800 Subject: [PATCH 09/50] updated rns --- docs/users-manual/getting-started/whats-new.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/users-manual/getting-started/whats-new.md b/docs/users-manual/getting-started/whats-new.md index 8b94194fb..72aaf20b7 100644 --- a/docs/users-manual/getting-started/whats-new.md +++ b/docs/users-manual/getting-started/whats-new.md @@ -58,9 +58,9 @@ Features: - Support has been added for the following CTAP 2.2 and YubiKey firmware version 5.8 features ([#299](https://github.com/Yubico/Yubico.NET.SDK/pull/299)): - - Persistent PinUvAuthToken (PPUAT): The SDK now supports the use of [Persistent PinUvAuthTokens (PPUATs)](xref:Fido2AuthTokens#persistent-pinuvauthtoken-ppuat), which are longer-lived auth tokens that can be used for read-only FIDO2 credential management operations, including [EnumerateRelyingParties()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateRelyingParties), [EnumerateCredentialsForRelyingParty()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateCredentialsForRelyingParty%28Yubico.YubiKey.Fido2.RelyingParty%29), and [GetCredentialMetadata()](xref:Yubico.YubiKey.Fido2.Fido2Session.GetCredentialMetadata). PPUATs enable applications to list discoverable credentials from YubiKeys without requiring repeated PIN entry. + - [Persistent PinUvAuthToken (PPUAT)](xref:Fido2AuthTokens#persistent-pinuvauthtoken-ppuat): PPUATs are longer-lived auth tokens that can be used for read-only FIDO2 credential management operations, including [EnumerateRelyingParties()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateRelyingParties), [EnumerateCredentialsForRelyingParty()](xref:Yubico.YubiKey.Fido2.Fido2Session.EnumerateCredentialsForRelyingParty%28Yubico.YubiKey.Fido2.RelyingParty%29), and [GetCredentialMetadata()](xref:Yubico.YubiKey.Fido2.Fido2Session.GetCredentialMetadata). PPUATs enable applications to list discoverable credentials from YubiKeys without requiring repeated PIN entry. - - thirdPartyPayment extension: The SDK now supports the [thirdPartyPayment extension](xref:Fido2ThirdPartyPayment), which enables YubiKeys to be used for payment authentication scenarios, including Secure Payment Confirmation (SPC) workflows, where the transaction initiator is not the relying party. + - [thirdPartyPayment extension](xref:Fido2ThirdPartyPayment): This extension enables YubiKeys to be used for payment authentication scenarios, including Secure Payment Confirmation (SPC) workflows, where the transaction initiator is not the relying party. - hmac-secret-mc extension: [GetHmacSecretExtension](xref:Yubico.YubiKey.Fido2.AuthenticatorData.GetHmacSecretExtension%28Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase%29) now handles both hmac-secret and hmac-secret-mc extensions when extracting and decrypting secrets. The hmac-secret-mc extension enables PRF (Pseudo-Random Function) during [MakeCredential()](xref:Yubico.YubiKey.Fido2.Fido2Session.MakeCredential%28Yubico.YubiKey.Fido2.MakeCredentialParameters%29). From 0a8eec583d18ae445227c3181a477d2c78bfac28 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Mon, 1 Dec 2025 11:46:14 -0800 Subject: [PATCH 10/50] removed statements about typical cert sizes, reworked chapter --- .../users-manual/application-piv/cert-size.md | 50 ++++++------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index a8800a6c4..5a5c97487 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -18,18 +18,12 @@ limitations under the License. --> # Maximum certificate sizes -It is possible to store up to 24 private key/certificate pairs in the PIV slots. However, -there are space limitations. - -In the real world, certificates are generally less than 1,000 bytes. Some large certs are -over 1,000 bytes, but rarely over 2,000. It is unlikely that you will run into limitations -on the YubiKey. - -Nonetheless, these are the space limitations for certs in the PIV application on the -YubiKey. +It is possible to store up to 24 private key/certificate pairs in the PIV slots for YubiKeys with firmware version 4.x and higher. However, there are limits to the size of each certificate and the total space available for all certificates. ## Maximum size for a single certificate +If you attempt to load a certificate that is larger than the key's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. + | YubiKey Version | Maximum Size in Bytes | |:---------------------:|:---------------------:| | before 4.0 (e.g. NEO) | 2025 | @@ -40,33 +34,19 @@ YubiKey. ## Total space available for certificates -Although a YubiKey 5.x will allow a 3052-byte cert in one of the slots, it will not be -able to store 24 certs that big. +Although YubiKeys with firmware version 4.x and higher will allow 3052-byte certificates, they will not be able to store 24 certificates of that size due to the key's total certificate space limit. Even if a YubiKey has empty certificate slots available, you cannot fill them once the maximum certificate space has been reached. -A NEO (pre-4.0), only has four slots, and will be able to hold four certs of the maximum +However, a YubiKey NEO, which only has four slots, will be able to hold four certs of the maximum length. -| YubiKey Version | Maximum Total Cert
Space Available | Number of Certs
at Size | Number of Certs
at Maximum Size | -|:---------------------:|:--------------------------------------:|:---------------------------:|:-----------------------------------:| -| before 4.0 (e.g. NEO) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | -| 4.x | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 4.x FIPS | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 5.x | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | -| 5.x FIPS | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | - -Note that that total amount of storage on a YubiKey (for certs, for PUT DATA objects, +Note that that total amount of storage on a YubiKey (for certs, PUT DATA objects, etc.) is about 51,000 bytes. Hence, if a YubiKey is loaded with 49,000 bytes of certs, -then there will be very little space left for anything else. - -## Summary - -On a 5.x YubiKey, it is possible to store a 3,052-byte cert in a slot. If a cert is -bigger than 3,052 bytes, the YubiKey will reject it and the SDK will throw an exception. - -It is certainly possible to store several 3,052-byte certs on a 5.x YubiKey, but once the -total size limit is reached, the YubiKey won't be able to store any more, even if some of -the slots are empty. - -However, because a real world application will probably not use certs bigger than 2,000 -bytes, it is not likely it will ever run into a total space limitation and will be able -to store up to 24 certs. \ No newline at end of file +there will be very little space left for anything else. + +| YubiKey Version | Maximum Total Cert
Space Available | Maximum Average
Cert Size | Number of Certs
at Maximum Size | +|:---------------------:|:--------------------------------------:|:-----------------------------:|:-----------------------------------:| +| before 4.0 (e.g. NEO) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | +| 4.x | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| 4.x FIPS | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| 5.x | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | +| 5.x FIPS | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | \ No newline at end of file From 56e0ec297bd360ed8f8088a040c07b5135f5362f Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Tue, 2 Dec 2025 10:17:59 -0800 Subject: [PATCH 11/50] spelled out certificates --- .../users-manual/application-piv/cert-size.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index 5a5c97487..a42c7df97 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -36,17 +36,17 @@ If you attempt to load a certificate that is larger than the key's maximum allow Although YubiKeys with firmware version 4.x and higher will allow 3052-byte certificates, they will not be able to store 24 certificates of that size due to the key's total certificate space limit. Even if a YubiKey has empty certificate slots available, you cannot fill them once the maximum certificate space has been reached. -However, a YubiKey NEO, which only has four slots, will be able to hold four certs of the maximum +However, a YubiKey NEO, which only has four slots, will be able to hold four certificates of the maximum length. -Note that that total amount of storage on a YubiKey (for certs, PUT DATA objects, -etc.) is about 51,000 bytes. Hence, if a YubiKey is loaded with 49,000 bytes of certs, +Note that that total amount of storage on a YubiKey (for certificates, PUT DATA objects, +etc.) is about 51,000 bytes. Hence, if a YubiKey is loaded with 49,000 bytes of certificates, there will be very little space left for anything else. -| YubiKey Version | Maximum Total Cert
Space Available | Maximum Average
Cert Size | Number of Certs
at Maximum Size | -|:---------------------:|:--------------------------------------:|:-----------------------------:|:-----------------------------------:| -| before 4.0 (e.g. NEO) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | -| 4.x | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 4.x FIPS | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 5.x | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | -| 5.x FIPS | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | \ No newline at end of file +| YubiKey Version | Maximum Total Certificate
Space Available | Maximum Average
Certificate Size | Number of Certificates
at Maximum Size | +|:---------------------:|:---------------------------------------------:|:------------------------------------:|:------------------------------------------:| +| before 4.0 (e.g. NEO) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | +| 4.x | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| 4.x FIPS | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| 5.x | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | +| 5.x FIPS | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | \ No newline at end of file From 485ca637b6c9702a7d79bc4801a182ef87b4f857 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Tue, 2 Dec 2025 10:35:08 -0800 Subject: [PATCH 12/50] wrote out model and firmware in tables --- .../users-manual/application-piv/cert-size.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index a42c7df97..a3d019005 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -24,13 +24,13 @@ It is possible to store up to 24 private key/certificate pairs in the PIV slots If you attempt to load a certificate that is larger than the key's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. -| YubiKey Version | Maximum Size in Bytes | -|:---------------------:|:---------------------:| -| before 4.0 (e.g. NEO) | 2025 | -| 4.x | 3052 | -| 4.x FIPS | 3052 | -| 5.x | 3052 | -| 5.x FIPS | 3052 | +| YubiKey (Model and Firmware) | Maximum Size in Bytes | +|:--------------------------------:|:---------------------:| +| NEO (prior to 4.x) | 2025 | +| 4 Series (4.x) | 3052 | +| 4 FIPS Series (4.x) | 3052 | +| 5 Series (5.x) | 3052 | +| 5 FIPS Series (5.x) | 3052 | ## Total space available for certificates @@ -43,10 +43,10 @@ Note that that total amount of storage on a YubiKey (for certificates, PUT DATA etc.) is about 51,000 bytes. Hence, if a YubiKey is loaded with 49,000 bytes of certificates, there will be very little space left for anything else. -| YubiKey Version | Maximum Total Certificate
Space Available | Maximum Average
Certificate Size | Number of Certificates
at Maximum Size | -|:---------------------:|:---------------------------------------------:|:------------------------------------:|:------------------------------------------:| -| before 4.0 (e.g. NEO) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | -| 4.x | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 4.x FIPS | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 5.x | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | -| 5.x FIPS | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | \ No newline at end of file +| YubiKey
(Model and Firmware) | Maximum Total Certificate
Space Available | Maximum Average
Certificate Size | Number of Certificates
at Maximum Size | +|:--------------------------------:|:---------------------------------------------:|:------------------------------------:|:------------------------------------------:| +| NEO (prior to 4.x) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | +| 4 Series (4.x) | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| 4 FIPS Series (4.x) | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| 5 Series (5.x) | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | +| 5 FIPS Series (5.x) | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | \ No newline at end of file From d3bd2aed96859a2ea224ebfd25ba28e2f2212d30 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Tue, 2 Dec 2025 10:57:03 -0800 Subject: [PATCH 13/50] added note about cert sizes in practice --- docs/users-manual/application-piv/cert-size.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index a3d019005..a664181fb 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -20,6 +20,9 @@ limitations under the License. --> It is possible to store up to 24 private key/certificate pairs in the PIV slots for YubiKeys with firmware version 4.x and higher. However, there are limits to the size of each certificate and the total space available for all certificates. +> [!NOTE] +> In practice, the size of a key/certificate pair is determined by the choice of algorithm and key length (e.g. RSA 1024 vs RSA 4096), certificate complexity (e.g. use of OIDs, size attributes), the presence of PIV attestation objects, etc. + ## Maximum size for a single certificate If you attempt to load a certificate that is larger than the key's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. From fefe4c07c462d0cf4598aea3bde350528539a580 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Tue, 2 Dec 2025 11:06:21 -0800 Subject: [PATCH 14/50] wrote out YubiKey --- docs/users-manual/application-piv/cert-size.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index a664181fb..c20f0c508 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -25,7 +25,7 @@ It is possible to store up to 24 private key/certificate pairs in the PIV slots ## Maximum size for a single certificate -If you attempt to load a certificate that is larger than the key's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. +If you attempt to load a certificate that is larger than the YubiKey's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. | YubiKey (Model and Firmware) | Maximum Size in Bytes | |:--------------------------------:|:---------------------:| @@ -37,7 +37,7 @@ If you attempt to load a certificate that is larger than the key's maximum allow ## Total space available for certificates -Although YubiKeys with firmware version 4.x and higher will allow 3052-byte certificates, they will not be able to store 24 certificates of that size due to the key's total certificate space limit. Even if a YubiKey has empty certificate slots available, you cannot fill them once the maximum certificate space has been reached. +Although YubiKeys with firmware version 4.x and higher will allow 3052-byte certificates, they will not be able to store 24 certificates of that size due to the YubiKey's total certificate space limit. Even if a YubiKey has empty certificate slots available, you cannot fill them once the maximum certificate space has been reached. However, a YubiKey NEO, which only has four slots, will be able to hold four certificates of the maximum length. From 38c5d2b9a4f985b861232c9a2f7c60a9e7e1f1f4 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Tue, 2 Dec 2025 14:51:55 -0800 Subject: [PATCH 15/50] added info from discussion with firmware team --- docs/users-manual/application-piv/cert-size.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index c20f0c508..70deed671 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -25,6 +25,8 @@ It is possible to store up to 24 private key/certificate pairs in the PIV slots ## Maximum size for a single certificate +The maximum allowable certificate size is determined by the YubiKey's APDU buffer size, which varies by firmware version. + If you attempt to load a certificate that is larger than the YubiKey's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. | YubiKey (Model and Firmware) | Maximum Size in Bytes | @@ -42,9 +44,7 @@ Although YubiKeys with firmware version 4.x and higher will allow 3052-byte cert However, a YubiKey NEO, which only has four slots, will be able to hold four certificates of the maximum length. -Note that that total amount of storage on a YubiKey (for certificates, PUT DATA objects, -etc.) is about 51,000 bytes. Hence, if a YubiKey is loaded with 49,000 bytes of certificates, -there will be very little space left for anything else. +Note that that total amount of storage in a YubiKey's PIV application (for certificates *plus* [PIV data objects](xref:UsersManualPivObjects)) is about 51,000 bytes. Therefore, if a YubiKey is loaded with 49,000 bytes of certificates, there will be very little space left for anything else. | YubiKey
(Model and Firmware) | Maximum Total Certificate
Space Available | Maximum Average
Certificate Size | Number of Certificates
at Maximum Size | |:--------------------------------:|:---------------------------------------------:|:------------------------------------:|:------------------------------------------:| From d1dc5f06f20c3f93c3ae3d46133c39b1b43ed984 Mon Sep 17 00:00:00 2001 From: Dennis Dyallo Date: Wed, 3 Dec 2025 15:27:33 +0100 Subject: [PATCH 16/50] docs: add updated example to check for extension support --- docs/users-manual/application-fido2/thirdpartypayment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/users-manual/application-fido2/thirdpartypayment.md b/docs/users-manual/application-fido2/thirdpartypayment.md index 235c94c29..195b1333a 100644 --- a/docs/users-manual/application-fido2/thirdpartypayment.md +++ b/docs/users-manual/application-fido2/thirdpartypayment.md @@ -33,7 +33,7 @@ Only YubiKeys with firmware version 5.8 and later support the thirdPartyPayment ```C# using (Fido2Session fido2Session = new Fido2Session(yubiKey)) { - if (fido2Session.AuthenticatorInfo.Extensions.Contains("thirdPartyPayment")) + if (fido2Session.AuthenticatorInfo.IsExtensionSupported(Extensions.ThirdPartyPayment)) { ... } From 18518b073272f426888e0fc54839838c8434936d Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Wed, 3 Dec 2025 08:40:37 -0800 Subject: [PATCH 17/50] changed toc name --- docs/users-manual/toc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/users-manual/toc.yml b/docs/users-manual/toc.yml index fc898612c..4ff398469 100644 --- a/docs/users-manual/toc.yml +++ b/docs/users-manual/toc.yml @@ -337,7 +337,7 @@ href: application-fido2/cred-blobs.md - name: Large blobs href: application-fido2/large-blobs.md - - name: Extensions + - name: Additional extensions items: - name: HMAC secret extension href: application-fido2/hmac-secret.md From 4a64f63fea29d1763267b313dc8fa814225d0000 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Wed, 3 Dec 2025 08:44:32 -0800 Subject: [PATCH 18/50] fixed hmac toc entry --- docs/users-manual/toc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/users-manual/toc.yml b/docs/users-manual/toc.yml index 4ff398469..30e63c4d7 100644 --- a/docs/users-manual/toc.yml +++ b/docs/users-manual/toc.yml @@ -339,7 +339,7 @@ href: application-fido2/large-blobs.md - name: Additional extensions items: - - name: HMAC secret extension + - name: HMAC secret extensions href: application-fido2/hmac-secret.md - name: Third-party payment extension href: application-fido2/thirdpartypayment.md From a064b5c1536ac11711f9918eef3182654c6b989e Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Wed, 3 Dec 2025 16:27:38 -0800 Subject: [PATCH 19/50] additional info and edits from FW discussion --- docs/users-manual/application-piv/cert-size.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index 70deed671..45b730c60 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -18,15 +18,15 @@ limitations under the License. --> # Maximum certificate sizes -It is possible to store up to 24 private key/certificate pairs in the PIV slots for YubiKeys with firmware version 4.x and higher. However, there are limits to the size of each certificate and the total space available for all certificates. +It is possible to store up to 24 private key/certificate pairs in the PIV slots for YubiKeys with firmware version 4.x and higher. However, there are limits to the size of each certificate and the total space available for all certificates. Once the total certificate storage space has been filled, you cannot load additional certificates onto the YubiKey. + +Keys, however, are stored in a separate, fixed memory layout. It is always possible to store 24 *keys* in a YubiKey's PIV application, as they are not subject to the certificate storage limits. > [!NOTE] > In practice, the size of a key/certificate pair is determined by the choice of algorithm and key length (e.g. RSA 1024 vs RSA 4096), certificate complexity (e.g. use of OIDs, size attributes), the presence of PIV attestation objects, etc. ## Maximum size for a single certificate -The maximum allowable certificate size is determined by the YubiKey's APDU buffer size, which varies by firmware version. - If you attempt to load a certificate that is larger than the YubiKey's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. | YubiKey (Model and Firmware) | Maximum Size in Bytes | @@ -37,6 +37,9 @@ If you attempt to load a certificate that is larger than the YubiKey's maximum a | 5 Series (5.x) | 3052 | | 5 FIPS Series (5.x) | 3052 | +> [!NOTE] +> The maximum allowable certificate size is determined by the YubiKey's APDU buffer size. For YubiKeys with firmware version 4.x and above, the buffer size is 3072. Certificates stored according to the PIV standard will have approximately 20 bytes of header data, including tag and length values, leaving 3052 bytes for the certificate itself. + ## Total space available for certificates Although YubiKeys with firmware version 4.x and higher will allow 3052-byte certificates, they will not be able to store 24 certificates of that size due to the YubiKey's total certificate space limit. Even if a YubiKey has empty certificate slots available, you cannot fill them once the maximum certificate space has been reached. @@ -44,7 +47,7 @@ Although YubiKeys with firmware version 4.x and higher will allow 3052-byte cert However, a YubiKey NEO, which only has four slots, will be able to hold four certificates of the maximum length. -Note that that total amount of storage in a YubiKey's PIV application (for certificates *plus* [PIV data objects](xref:UsersManualPivObjects)) is about 51,000 bytes. Therefore, if a YubiKey is loaded with 49,000 bytes of certificates, there will be very little space left for anything else. +Note that the total amount of NVM (non-volatile memory) in a YubiKey's PIV application, which stores certificates (including the attestation certificate) *plus* [PIV data objects](xref:UsersManualPivObjects), is 51,200 bytes. Therefore, if a YubiKey is loaded with a lot of certificate data (for example, 49,000 bytes worth), there will be very little space left for anything else. | YubiKey
(Model and Firmware) | Maximum Total Certificate
Space Available | Maximum Average
Certificate Size | Number of Certificates
at Maximum Size | |:--------------------------------:|:---------------------------------------------:|:------------------------------------:|:------------------------------------------:| From f9d6254baee748c99a43642fe7e5c4505bcf478e Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Thu, 4 Dec 2025 08:17:16 -0800 Subject: [PATCH 20/50] updated release date, added 2 doc rns --- docs/users-manual/getting-started/whats-new.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/users-manual/getting-started/whats-new.md b/docs/users-manual/getting-started/whats-new.md index 3f1881452..27e8a74dd 100644 --- a/docs/users-manual/getting-started/whats-new.md +++ b/docs/users-manual/getting-started/whats-new.md @@ -20,7 +20,7 @@ Here you can find all of the updates and release notes for published versions of ### 1.15.0 -Release date: December 3rd, 2025 +Release date: December 4th, 2025 Features: @@ -36,6 +36,11 @@ Bug Fixes: Documentation: +- Docs covering SDK support for the following FIDO2 extensions have been added to the User's Manual: + + - [third-party payment](xref:Fido2ThirdPartyPayment) ([#349](https://github.com/Yubico/Yubico.NET.SDK/pull/349)) + - [hmac-secret-mc](xref:Fido2HmacSecret) ([#350](https://github.com/Yubico/Yubico.NET.SDK/pull/350)) + - Comprehensive docs covering SDK support for the [Persistent PinUvAuthToken (PPUAT)](xref:Fido2AuthTokens#persistent-pinuvauthtoken-ppuat) have been added to the User's Manual. ([#333](https://github.com/Yubico/Yubico.NET.SDK/pull/333)) - NFC instructions have been added to the [FIDO2 reset](xref:Fido2Reset) docs. ([#341](https://github.com/Yubico/Yubico.NET.SDK/pull/341)) From 0aa0a6f5166ac6aa7c766440c4e53db83e8654a4 Mon Sep 17 00:00:00 2001 From: Dennis Dyallo Date: Sun, 7 Dec 2025 03:11:55 +0100 Subject: [PATCH 21/50] ci: persistCredentials on necessary step --- .github/workflows/deploy-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 945b6e855..f6135d57c 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -55,7 +55,7 @@ jobs: ref: ${{ inputs.gitops-branch }} token: ${{ steps.generate_token.outputs.token }} path: gitops - persist-credentials: false + persist-credentials: true - name: Update GitOps resources run: sed -i "s#/yesdk/yesdk-docserver:.*\$#/yesdk/yesdk-docserver:$IMAGE_TAG#" ./k8s/yesdk/kustomization.yaml From 79611add4c6b36eb16b2763af2c2a46801447b76 Mon Sep 17 00:00:00 2001 From: StepSecurity Bot Date: Tue, 9 Dec 2025 13:11:23 +0000 Subject: [PATCH 22/50] [StepSecurity] Apply security best practices Signed-off-by: StepSecurity Bot --- .github/dependabot.yml | 67 ++++++++++++++++++++++- .github/workflows/build-nativeshims.yml | 35 +++++++++++- .github/workflows/build-pull-requests.yml | 5 ++ .github/workflows/build.yml | 18 ++++++ .github/workflows/claude.yml | 8 +++ .github/workflows/codeql-analysis.yml | 5 ++ .github/workflows/dependency-review.yml | 27 +++++++++ .github/workflows/deploy-docs.yml | 10 ++++ .github/workflows/scorecard.yml | 7 ++- .github/workflows/test-macos.yml | 8 +++ .github/workflows/test-ubuntu.yml | 8 +++ .github/workflows/test-windows.yml | 8 +++ .github/workflows/test.yml | 15 +++++ .github/workflows/upload-docs.yml | 5 ++ .github/workflows/verify-code-style.yml | 8 +++ Dockerfile | 2 +- 16 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/dependency-review.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b2974e49d..c5e77bf4b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -31,4 +31,69 @@ updates: groups: github-actions: patterns: - - "*" \ No newline at end of file + - "*" + + - package-ecosystem: docker + directory: / + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.Core/src + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.Core/tests + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/examples/Fido2SampleCode + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/examples/OathSampleCode + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/examples/PivSampleCode + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/examples/SharedSampleCode + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/examples/U2fSampleCode + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/src + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/tests/integration + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/tests/sandbox + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/tests/unit + schedule: + interval: daily + + - package-ecosystem: nuget + directory: /Yubico.YubiKey/tests/utilities + schedule: + interval: daily diff --git a/.github/workflows/build-nativeshims.yml b/.github/workflows/build-nativeshims.yml index 8970eba2c..149e3161d 100644 --- a/.github/workflows/build-nativeshims.yml +++ b/.github/workflows/build-nativeshims.yml @@ -29,11 +29,19 @@ on: schedule: - cron: '0 0 * * *' # Every day at midnight +permissions: + contents: read + jobs: build-windows: name: Build Windows runs-on: windows-2022 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false @@ -79,6 +87,11 @@ jobs: name: Build Linux (amd64) runs-on: ubuntu-24.04 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false @@ -231,6 +244,11 @@ jobs: name: Build Linux (arm64) runs-on: ubuntu-24.04 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false @@ -304,7 +322,7 @@ jobs: bash ./build-linux-arm64.sh fi - name: Set up QEMU for ARM64 testing - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 with: platforms: arm64 - name: Test on Ubuntu 18.04 (glibc 2.27) @@ -387,6 +405,11 @@ jobs: name: Build macOS runs-on: macos-14 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false @@ -421,6 +444,11 @@ jobs: PACKAGE_VERSION: ${{ github.event.inputs.version != '' && github.event.inputs.version || '1.0.0' }} GITHUB_REPO_URL: https://github.com/${{ github.repository }} steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: Download contents, set metadata and package uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - run: | @@ -460,6 +488,11 @@ jobs: packages: write if: ${{ github.event.inputs.push-to-dev == 'true' }} steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: NuGet Package NativeShims diff --git a/.github/workflows/build-pull-requests.yml b/.github/workflows/build-pull-requests.yml index 52ab19b9b..3e4ce8335 100644 --- a/.github/workflows/build-pull-requests.yml +++ b/.github/workflows/build-pull-requests.yml @@ -47,6 +47,11 @@ jobs: needs: run-tests steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b08e17032..58abc6d9a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,9 @@ on: schedule: - cron: '0 0 * * *' # Every day at midnight +permissions: + contents: read + jobs: run-tests: name: Run tests @@ -76,6 +79,11 @@ jobs: symbols-packages-id: ${{ steps.symbols-upload.outputs.artifact-id }} assemblies-id: ${{ steps.assemblies-upload.outputs.artifact-id }} steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false @@ -187,6 +195,11 @@ jobs: contents: read packages: write steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: Nuget Packages @@ -209,6 +222,11 @@ jobs: needs: [run-tests, build-artifacts, publish-internal, upload-docs] if: always() steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: Generate build summary env: # Pass job results into the environment diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 64e5fbe76..91b08c700 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -10,6 +10,9 @@ on: pull_request_review: types: [submitted] +permissions: + contents: read + jobs: claude: if: | @@ -25,6 +28,11 @@ jobs: id-token: write actions: read # Required for Claude to read CI results on PRs steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: Checkout repository uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2661b92f3..b8546b4e5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -54,6 +54,11 @@ jobs: runs-on: windows-2022 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: Checkout repository uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 000000000..d9284f67a --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,27 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + + - name: 'Checkout Repository' + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - name: 'Dependency Review' + uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index f6135d57c..a6a309006 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -26,6 +26,11 @@ jobs: runs-on: ubuntu-latest steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: Check out current repo uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: @@ -82,6 +87,11 @@ jobs: needs: deploy steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 0eb0df465..bf7e0e54d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -34,6 +34,11 @@ jobs: # actions: read steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: "Checkout code" uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: @@ -74,6 +79,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@497990dfed22177a82ba1bbab381bc8f6d27058f # v3.31.6 with: sarif_file: results.sarif diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index f414e7b4e..8bafbaac1 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -18,6 +18,9 @@ on: workflow_dispatch: workflow_call: +permissions: + contents: read + jobs: test: name: MacOS @@ -27,6 +30,11 @@ jobs: packages: read steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 9a0bf445a..6abd15d77 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -18,6 +18,9 @@ on: workflow_dispatch: workflow_call: +permissions: + contents: read + jobs: test: name: Ubuntu @@ -27,6 +30,11 @@ jobs: packages: read steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 0c9d90be4..6b5958522 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -18,6 +18,9 @@ on: workflow_dispatch: workflow_call: +permissions: + contents: read + jobs: test: name: Windows @@ -27,6 +30,11 @@ jobs: contents: read steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7390c18c7..75d0f8924 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -82,6 +82,11 @@ jobs: if: inputs.build-coverage-report == true steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - name: Combine Coverage Reports # This is because one report is produced per project, and we want one result for all of them. uses: danielpalme/ReportGenerator-GitHub-Action@dcdfb6e704e87df6b2ed0cf123a6c9f69e364869 # 5.5.0 @@ -121,6 +126,11 @@ jobs: if: github.event_name == 'pull_request' steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - name: Download coverage results uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: @@ -139,6 +149,11 @@ jobs: if: github.event_name == 'pull_request' steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - name: "Add PR Comment: Test Results (Windows)" diff --git a/.github/workflows/upload-docs.yml b/.github/workflows/upload-docs.yml index fb3b0e5c1..164a1ddd0 100644 --- a/.github/workflows/upload-docs.yml +++ b/.github/workflows/upload-docs.yml @@ -44,6 +44,11 @@ jobs: image-hash: ${{ steps.push_image.outputs.imagehash }} steps: # Checkout the local repository as we need the Dockerfile and other things even for this step. + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/.github/workflows/verify-code-style.yml b/.github/workflows/verify-code-style.yml index b1fd15548..1cd62be0d 100644 --- a/.github/workflows/verify-code-style.yml +++ b/.github/workflows/verify-code-style.yml @@ -27,12 +27,20 @@ on: # - '**.csproj' # - '**.sln' # - '.github/workflows/check-code-formatting.yml' +permissions: + contents: read + jobs: verify-code-style: name: "Verify code style" runs-on: windows-latest steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + with: + egress-policy: audit + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false diff --git a/Dockerfile b/Dockerfile index bea9986d0..c9ba14e22 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM nginx:alpine +FROM nginx:alpine@sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14 ARG UID=1000 ARG GID=1000 From cb2801d808128593640255a4fb5fedf99404f3f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:27:09 +0000 Subject: [PATCH 23/50] build(deps): bump nginx from `b3c656d` to `289deca` Bumps nginx from `b3c656d` to `289deca`. --- updated-dependencies: - dependency-name: nginx dependency-version: alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c9ba14e22..2aca42b41 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM nginx:alpine@sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14 +FROM nginx:alpine@sha256:289decab414250121a93c3f1b8316b9c69906de3a4993757c424cb964169ad42 ARG UID=1000 ARG GID=1000 From df9f654770060d17a828d712adfbbb1f03a3917a Mon Sep 17 00:00:00 2001 From: Dennis Dyallo Date: Wed, 10 Dec 2025 15:29:04 +0100 Subject: [PATCH 24/50] ci: set dependabot update frequency --- .github/dependabot.yml | 67 ++++-------------------------------------- 1 file changed, 5 insertions(+), 62 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c5e77bf4b..0c938aece 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -24,7 +24,7 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "monthly" + interval: "weekly" day: "wednesday" time: "09:00" timezone: "Europe/Stockholm" @@ -36,64 +36,7 @@ updates: - package-ecosystem: docker directory: / schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.Core/src - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.Core/tests - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/examples/Fido2SampleCode - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/examples/OathSampleCode - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/examples/PivSampleCode - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/examples/SharedSampleCode - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/examples/U2fSampleCode - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/src - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/tests/integration - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/tests/sandbox - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/tests/unit - schedule: - interval: daily - - - package-ecosystem: nuget - directory: /Yubico.YubiKey/tests/utilities - schedule: - interval: daily + interval: "weekly" + day: "wednesday" + time: "09:00" + timezone: "Europe/Stockholm" From 326c54141267e5b3ce661ff47da784a5acd214b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:30:17 +0000 Subject: [PATCH 25/50] build(deps): bump the github-actions group with 8 updates Bumps the github-actions group with 8 updates: | Package | From | To | | --- | --- | --- | | [step-security/harden-runner](https://github.com/step-security/harden-runner) | `2.13.3` | `2.14.0` | | [actions/checkout](https://github.com/actions/checkout) | `4.2.2` | `6.0.1` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4.6.1` | `5.0.0` | | [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) | `1.0.9` | `1.0.23` | | [github/codeql-action](https://github.com/github/codeql-action) | `3.31.6` | `4.31.7` | | [actions/create-github-app-token](https://github.com/actions/create-github-app-token) | `2.2.0` | `2.2.1` | | [ossf/scorecard-action](https://github.com/ossf/scorecard-action) | `2.4.1` | `2.4.3` | | [danielpalme/ReportGenerator-GitHub-Action](https://github.com/danielpalme/reportgenerator-github-action) | `5.5.0` | `5.5.1` | Updates `step-security/harden-runner` from 2.13.3 to 2.14.0 - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/df199fb7be9f65074067a9eb93f12bb4c5547cf2...20cf305ff2072d973412fa9b1e3a4f227bda3c76) Updates `actions/checkout` from 4.2.2 to 6.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.2...8e8c483db84b4bee98b60c0593521ed34d9990e8) Updates `actions/upload-artifact` from 4.6.1 to 5.0.0 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4.6.1...330a01c490aca151604b8cf639adc76d48f6c5d4) Updates `anthropics/claude-code-action` from 1.0.9 to 1.0.23 - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](https://github.com/anthropics/claude-code-action/compare/426380f01bad0a17200865605a85cb28926dccbf...f0c8eb29807907de7f5412d04afceb5e24817127) Updates `github/codeql-action` from 3.31.6 to 4.31.7 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3.31.6...cf1bb45a277cb3c205638b2cd5c984db1c46a412) Updates `actions/create-github-app-token` from 2.2.0 to 2.2.1 - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Commits](https://github.com/actions/create-github-app-token/compare/7e473efe3cb98aa54f8d4bac15400b15fad77d94...29824e69f54612133e76f7eaac726eef6c875baf) Updates `ossf/scorecard-action` from 2.4.1 to 2.4.3 - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/f49aabe0b5af0936a0987cfb85d86b75731b0186...4eaacf0543bb3f2c246792bd56e8cdeffafb205a) Updates `danielpalme/ReportGenerator-GitHub-Action` from 5.5.0 to 5.5.1 - [Release notes](https://github.com/danielpalme/reportgenerator-github-action/releases) - [Commits](https://github.com/danielpalme/reportgenerator-github-action/compare/dcdfb6e704e87df6b2ed0cf123a6c9f69e364869...ee0ae774f6d3afedcbd1683c1ab21b83670bdf8e) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.14.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/upload-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: anthropics/claude-code-action dependency-version: 1.0.23 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action dependency-version: 4.31.7 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/create-github-app-token dependency-version: 2.2.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: danielpalme/ReportGenerator-GitHub-Action dependency-version: 5.5.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-nativeshims.yml | 20 ++++++++++---------- .github/workflows/build-pull-requests.yml | 4 ++-- .github/workflows/build.yml | 8 ++++---- .github/workflows/claude.yml | 6 +++--- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/dependency-review.yml | 4 ++-- .github/workflows/deploy-docs.yml | 14 +++++++------- .github/workflows/scorecard.yml | 10 +++++----- .github/workflows/test-macos.yml | 4 ++-- .github/workflows/test-ubuntu.yml | 4 ++-- .github/workflows/test-windows.yml | 4 ++-- .github/workflows/test.yml | 8 ++++---- .github/workflows/upload-docs.yml | 4 ++-- .github/workflows/verify-code-style.yml | 4 ++-- 14 files changed, 51 insertions(+), 51 deletions(-) diff --git a/.github/workflows/build-nativeshims.yml b/.github/workflows/build-nativeshims.yml index 149e3161d..1fe116b1c 100644 --- a/.github/workflows/build-nativeshims.yml +++ b/.github/workflows/build-nativeshims.yml @@ -38,11 +38,11 @@ jobs: runs-on: windows-2022 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - run: | @@ -88,11 +88,11 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Install Zig (pinned version) @@ -245,11 +245,11 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Install Zig (pinned version) @@ -406,11 +406,11 @@ jobs: runs-on: macos-14 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - run: | @@ -445,7 +445,7 @@ jobs: GITHUB_REPO_URL: https://github.com/${{ github.repository }} steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit @@ -489,7 +489,7 @@ jobs: if: ${{ github.event.inputs.push-to-dev == 'true' }} steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit diff --git a/.github/workflows/build-pull-requests.yml b/.github/workflows/build-pull-requests.yml index 3e4ce8335..5feb4774d 100644 --- a/.github/workflows/build-pull-requests.yml +++ b/.github/workflows/build-pull-requests.yml @@ -48,11 +48,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58abc6d9a..2d43f6b74 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,11 +80,11 @@ jobs: assemblies-id: ${{ steps.assemblies-upload.outputs.artifact-id }} steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 @@ -196,7 +196,7 @@ jobs: packages: write steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit @@ -223,7 +223,7 @@ jobs: if: always() steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 91b08c700..a04944e5c 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -29,19 +29,19 @@ jobs: actions: read # Required for Claude to read CI results on PRs steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 1 persist-credentials: false - name: Run Claude Code id: claude - uses: anthropics/claude-code-action@426380f01bad0a17200865605a85cb28926dccbf # v1.0.9 + uses: anthropics/claude-code-action@f0c8eb29807907de7f5412d04afceb5e24817127 # v1.0.23 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b8546b4e5..c936a588c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -55,12 +55,12 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -74,7 +74,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: # Override automatic language detection to only analyze C# # C/C++ code in Yubico.NativeShims is built separately (requires CMake/vcpkg) @@ -87,4 +87,4 @@ jobs: NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index d9284f67a..83c9c121a 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - name: 'Checkout Repository' - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: 'Dependency Review' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index a6a309006..6212e1136 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -27,12 +27,12 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - name: Check out current repo - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: path: self persist-credentials: false @@ -46,7 +46,7 @@ jobs: - name: Generate GitHub App token id: generate_token - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: 800408 # Yubico Docs owner: Yubico @@ -54,7 +54,7 @@ jobs: private-key: ${{ secrets.GH_APP_YUBICO_DOCS_PRIVATE_KEY }} - name: Check out docs-gitops repo (${{ inputs.gitops-branch }} branch) - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: repository: Yubico/docs-gitops ref: ${{ inputs.gitops-branch }} @@ -88,12 +88,12 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -105,7 +105,7 @@ jobs: - name: Generate GitHub App token id: generate_token - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: 260767 # Yubico Commit Status Reader owner: Yubico diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index bf7e0e54d..e13cfa30b 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -35,17 +35,17 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - name: "Checkout code" - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif @@ -70,7 +70,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: SARIF file path: results.sarif @@ -79,6 +79,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@497990dfed22177a82ba1bbab381bc8f6d27058f # v3.31.6 + uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: sarif_file: results.sarif diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index 8bafbaac1..ebb53a304 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -31,11 +31,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 6abd15d77..17860d1c0 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -31,11 +31,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 6b5958522..ba502f6d2 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -31,11 +31,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 75d0f8924..3ef7727f8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -83,13 +83,13 @@ jobs: if: inputs.build-coverage-report == true steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - name: Combine Coverage Reports # This is because one report is produced per project, and we want one result for all of them. - uses: danielpalme/ReportGenerator-GitHub-Action@dcdfb6e704e87df6b2ed0cf123a6c9f69e364869 # 5.5.0 + uses: danielpalme/ReportGenerator-GitHub-Action@ee0ae774f6d3afedcbd1683c1ab21b83670bdf8e # 5.5.1 with: reports: "**/*.cobertura.xml" # REQUIRED # The coverage reports that should be parsed (separated by semicolon). Globbing is supported. targetdir: "${{ github.workspace }}" # REQUIRED # The directory where the generated report should be saved. @@ -127,7 +127,7 @@ jobs: if: github.event_name == 'pull_request' steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit @@ -150,7 +150,7 @@ jobs: if: github.event_name == 'pull_request' steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit diff --git a/.github/workflows/upload-docs.yml b/.github/workflows/upload-docs.yml index 164a1ddd0..28847cafa 100644 --- a/.github/workflows/upload-docs.yml +++ b/.github/workflows/upload-docs.yml @@ -45,11 +45,11 @@ jobs: steps: # Checkout the local repository as we need the Dockerfile and other things even for this step. - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false diff --git a/.github/workflows/verify-code-style.yml b/.github/workflows/verify-code-style.yml index 1cd62be0d..91ee3afb1 100644 --- a/.github/workflows/verify-code-style.yml +++ b/.github/workflows/verify-code-style.yml @@ -37,11 +37,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@df199fb7be9f65074067a9eb93f12bb4c5547cf2 # v2.13.3 + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 with: egress-policy: audit - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 From de90d2d82a9aa46fca6dfd2f0083841714e763b5 Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Thu, 11 Dec 2025 11:16:16 -0800 Subject: [PATCH 26/50] updated product names, header in tables --- .../users-manual/application-piv/cert-size.md | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/users-manual/application-piv/cert-size.md b/docs/users-manual/application-piv/cert-size.md index 45b730c60..c7d2c4482 100644 --- a/docs/users-manual/application-piv/cert-size.md +++ b/docs/users-manual/application-piv/cert-size.md @@ -29,13 +29,13 @@ Keys, however, are stored in a separate, fixed memory layout. It is always possi If you attempt to load a certificate that is larger than the YubiKey's maximum allowable certificate size (as indicated in the table below), the YubiKey will reject it, and the SDK will throw an exception. -| YubiKey (Model and Firmware) | Maximum Size in Bytes | -|:--------------------------------:|:---------------------:| -| NEO (prior to 4.x) | 2025 | -| 4 Series (4.x) | 3052 | -| 4 FIPS Series (4.x) | 3052 | -| 5 Series (5.x) | 3052 | -| 5 FIPS Series (5.x) | 3052 | +| YubiKey Model (and Firmware Version)| Maximum Size in Bytes | +|:-----------------------------------:|:---------------------:| +| YubiKey NEO (prior to 4.x) | 2025 | +| YubiKey 4 Series (4.x) | 3052 | +| YubiKey 4 FIPS Series (4.x) | 3052 | +| YubiKey 5 Series (5.x) | 3052 | +| YubiKey 5 FIPS Series (5.x) | 3052 | > [!NOTE] > The maximum allowable certificate size is determined by the YubiKey's APDU buffer size. For YubiKeys with firmware version 4.x and above, the buffer size is 3072. Certificates stored according to the PIV standard will have approximately 20 bytes of header data, including tag and length values, leaving 3052 bytes for the certificate itself. @@ -44,15 +44,14 @@ If you attempt to load a certificate that is larger than the YubiKey's maximum a Although YubiKeys with firmware version 4.x and higher will allow 3052-byte certificates, they will not be able to store 24 certificates of that size due to the YubiKey's total certificate space limit. Even if a YubiKey has empty certificate slots available, you cannot fill them once the maximum certificate space has been reached. -However, a YubiKey NEO, which only has four slots, will be able to hold four certificates of the maximum -length. +However, a YubiKey NEO, which only has four slots, will be able to hold four certificates of the maximum length. -Note that the total amount of NVM (non-volatile memory) in a YubiKey's PIV application, which stores certificates (including the attestation certificate) *plus* [PIV data objects](xref:UsersManualPivObjects), is 51,200 bytes. Therefore, if a YubiKey is loaded with a lot of certificate data (for example, 49,000 bytes worth), there will be very little space left for anything else. +| YubiKey Model
(and Firmware Version) | Maximum Total Certificate
Space Available | Maximum Average
Certificate Size | Number of Certificates
at Maximum Size | +|:----------------------------------------:|:---------------------------------------------:|:------------------------------------:|:------------------------------------------:| +| YubiKey NEO (prior to 4.x) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | +| YubiKey 4 Series (4.x) | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| YubiKey 4 FIPS Series (4.x) | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | +| YubiKey 5 Series (5.x) | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | +| YubiKey 5 FIPS Series (5.x) | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | -| YubiKey
(Model and Firmware) | Maximum Total Certificate
Space Available | Maximum Average
Certificate Size | Number of Certificates
at Maximum Size | -|:--------------------------------:|:---------------------------------------------:|:------------------------------------:|:------------------------------------------:| -| NEO (prior to 4.x) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | -| 4 Series (4.x) | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 4 FIPS Series (4.x) | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | -| 5 Series (5.x) | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | -| 5 FIPS Series (5.x) | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | \ No newline at end of file +Note that the total amount of NVM (non-volatile memory) in a YubiKey's PIV application, which stores certificates (including the attestation certificate) *plus* [PIV data objects](xref:UsersManualPivObjects), is 51,200 bytes. Therefore, if a YubiKey is loaded with a lot of certificate data (for example, 49,000 bytes' worth), there will be very little space left for anything else. \ No newline at end of file From 26dd00e4f3a7a772a3fddf6a8197ac9ace9289ae Mon Sep 17 00:00:00 2001 From: Dennis Dyallo Date: Mon, 15 Dec 2025 10:28:58 +0100 Subject: [PATCH 27/50] refactor: simplify command APDU creation in SendCommand method --- Yubico.YubiKey/src/Yubico/YubiKey/SmartCardConnection.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Yubico.YubiKey/src/Yubico/YubiKey/SmartCardConnection.cs b/Yubico.YubiKey/src/Yubico/YubiKey/SmartCardConnection.cs index 17757e259..8ea5aa870 100644 --- a/Yubico.YubiKey/src/Yubico/YubiKey/SmartCardConnection.cs +++ b/Yubico.YubiKey/src/Yubico/YubiKey/SmartCardConnection.cs @@ -123,9 +123,11 @@ public virtual TResponse SendCommand(IYubiKeyCommand yubiK SelectApplication(); } + var commandApdu = yubiKeyCommand.CreateCommandApdu(); + var commandType = yubiKeyCommand.GetType(); var responseApdu = _apduPipeline.Invoke( - yubiKeyCommand.CreateCommandApdu(), - yubiKeyCommand.GetType(), + commandApdu, + commandType, typeof(TResponse)); return yubiKeyCommand.CreateResponseForApdu(responseApdu); From 2c7454afa23e43b25c68329160facc0de76f8264 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 08:08:36 +0000 Subject: [PATCH 28/50] build(deps): bump nginx from `289deca` to `052b75a` Bumps nginx from `289deca` to `052b75a`. --- updated-dependencies: - dependency-name: nginx dependency-version: alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2aca42b41..14510c395 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM nginx:alpine@sha256:289decab414250121a93c3f1b8316b9c69906de3a4993757c424cb964169ad42 +FROM nginx:alpine@sha256:052b75ab72f690f33debaa51c7e08d9b969a0447a133eb2b99cc905d9188cb2b ARG UID=1000 ARG GID=1000 From a11f6a2a967d35f1d45b4a6e657ee373ab090307 Mon Sep 17 00:00:00 2001 From: Dennis Dyall Date: Thu, 18 Dec 2025 11:41:33 +0100 Subject: [PATCH 29/50] refactor: removed unused class ConnectionManager.cs --- .../src/Yubico/YubiKey/ConnectionManager.cs | 318 ----------------- .../Yubico/YubiKey/ConnectionManagerTests.cs | 324 ------------------ 2 files changed, 642 deletions(-) delete mode 100644 Yubico.YubiKey/src/Yubico/YubiKey/ConnectionManager.cs delete mode 100644 Yubico.YubiKey/tests/unit/Yubico/YubiKey/ConnectionManagerTests.cs diff --git a/Yubico.YubiKey/src/Yubico/YubiKey/ConnectionManager.cs b/Yubico.YubiKey/src/Yubico/YubiKey/ConnectionManager.cs deleted file mode 100644 index f62977ca5..000000000 --- a/Yubico.YubiKey/src/Yubico/YubiKey/ConnectionManager.cs +++ /dev/null @@ -1,318 +0,0 @@ -// Copyright 2025 Yubico AB -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Threading; -using Yubico.Core.Devices; -using Yubico.Core.Devices.Hid; -using Yubico.Core.Devices.SmartCard; - -namespace Yubico.YubiKey -{ - /// - /// A service class that tracks open connections to the YubiKeys on the device. - /// - /// - /// - /// The YubiKey is fundamentally a single threaded device. Even if you are connecting through different USB interfaces, - /// such as Smart Card and HID Keyboard, the YubiKey can still only process a single request at a time. Device event - /// notifications now introduces implicit multi-threading into the SDK. We now need to be more aware of the active - /// connection state of any particular YubiKey. Even an enumeration can be disruptive, since we need to interrogate - /// the device in order to find its device properties. - /// - /// - /// This class is meant to be used as a service / singleton within the SDK. Whenever you need to create a connection - /// to a YubiKey, call the - /// method. Usage of this class should avoid the creation of more than one connection to a single physical YubiKey. - /// Connecting to different YubiKeys at once is fine, just not to a single key. - /// - /// - // JUSTIFICATION: This class is a singleton, which means its lifetime will span the process lifetime. It contains - // a lock which is disposable, so we must call its Dispose method at some point. The only reasonable time to do that - // is in this class's finalizer. This analyzer doesn't seem to see this and still warns. -#pragma warning disable CA1001 - internal class ConnectionManager -#pragma warning restore CA1001 - { - // Easy thread-safe singleton pattern using Lazy<> - private static readonly Lazy _instance = - new Lazy(() => new ConnectionManager()); - - /// - /// Gets the process-global singleton instance of the connection manager. - /// - public static ConnectionManager Instance => _instance.Value; - - /// - /// Determines if the given device object supports the requested YubiKey application. - /// - /// A concrete device object from Yubico.Core. - /// An application of the YubiKey. - /// `true` if the device object supports the application, `false` otherwise. - // This function uses C# 8.0 pattern matching to build a concise table. - public static bool DeviceSupportsApplication(IDevice device, YubiKeyApplication application) => - (device, application) switch - { - // FIDO interface - (IHidDevice { UsagePage: HidUsagePage.Fido }, YubiKeyApplication.FidoU2f) => true, - (IHidDevice { UsagePage: HidUsagePage.Fido }, YubiKeyApplication.Fido2) => true, - // Keyboard interface - (IHidDevice { UsagePage: HidUsagePage.Keyboard }, YubiKeyApplication.Otp) => true, - // All Smart Card based interfaces - (ISmartCardDevice _, YubiKeyApplication.Management) => true, - (ISmartCardDevice _, YubiKeyApplication.Oath) => true, - (ISmartCardDevice _, YubiKeyApplication.Piv) => true, - (ISmartCardDevice _, YubiKeyApplication.OpenPgp) => true, - (ISmartCardDevice _, YubiKeyApplication.InterIndustry) => true, - (ISmartCardDevice _, YubiKeyApplication.SecurityDomain) => true, - (ISmartCardDevice _, YubiKeyApplication.YubiHsmAuth) => true, - // NB: Certain past models of YK NEO and YK 4 supported these applications over CCID - (ISmartCardDevice _, YubiKeyApplication.FidoU2f) => true, - (ISmartCardDevice _, YubiKeyApplication.Fido2) => true, - (ISmartCardDevice _, YubiKeyApplication.Otp) => true, - // NFC interface - (ISmartCardDevice { Kind: SmartCardConnectionKind.Nfc }, YubiKeyApplication.OtpNdef) => true, - _ => false - }; - - private readonly HashSet _openConnections = new HashSet(); - private readonly ReaderWriterLockSlim _hashSetLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - - /// - /// Finalizes the ConnectionManager singleton - /// - /// - /// As this class contains a disposable resource, we need some place to properly dispose of it. The finalizer - /// is the only real chance we get to invoke this. - /// - ~ConnectionManager() - { - _hashSetLock.Dispose(); - } - - /// - /// Tries to connect to a known application on the YubiKey, failing if a connection to that YubiKey (regardless - /// of the application) already exists. - /// - /// - /// The YubiKey that we are attempting to connect to. - /// - /// - /// The actual physical device exposed by the YubiKey that we're attempting to connect to. - /// - /// - /// The YubiKey application that we're attempting to connect to. - /// - /// - /// The connection, if established. `null` otherwise. - /// - /// - /// 'true' if the connection was established, 'false' if there is already an outstanding connection to this - /// device. Note that this method throws exceptions for all other failure modes. - /// - /// - /// The specified device does not support requested application. - /// - /// - /// The device type is not recognized. - /// - public bool TryCreateConnection( - IYubiKeyDevice yubiKeyDevice, - IDevice device, - YubiKeyApplication application, - [MaybeNullWhen(returnValue: false)] - out IYubiKeyConnection connection) - { - if (!DeviceSupportsApplication(device, application)) - { - throw new ArgumentException( - ExceptionMessages.DeviceDoesNotSupportApplication, - nameof(application)); - } - - // Since taking a write lock is potentially very expensive, let's try and make a best effort to see if the - // YubiKey is already present. This way we can fail fast. - _hashSetLock.EnterReadLock(); - - try - { - if (_openConnections.Contains(yubiKeyDevice)) - { - connection = null; - - return false; - } - } - finally - { - _hashSetLock.ExitReadLock(); - } - - // The YubiKey wasn't present just a few microseconds ago, so hopefully we will be able to succeed in - // establishing a connection to it. - _hashSetLock.EnterWriteLock(); - - try - { - // We still need to double check that the key wasn't added in the time between exiting the read lock - // and entering the write lock. - if (_openConnections.Contains(yubiKeyDevice)) - { - connection = null; - - return false; - } - - connection = device switch - { - IHidDevice { UsagePage: HidUsagePage.Fido } d => new FidoConnection(d), - IHidDevice { UsagePage: HidUsagePage.Keyboard } d => new KeyboardConnection(d), - ISmartCardDevice d => new SmartCardConnection(d, application), - _ => throw new NotSupportedException(ExceptionMessages.DeviceTypeNotRecognized) - }; - - _ = _openConnections.Add(yubiKeyDevice); - } - finally - { - _hashSetLock.ExitWriteLock(); - } - - return true; - } - - /// - /// Tries to connect to an arbitrary application on the YubiKey, failing if a connection to that YubiKey already - /// exists. - /// - /// - /// The YubiKey that we are attempting to connect to. - /// - /// - /// The actual physical device exposed by the YubiKey that we're attempting to connect to. - /// - /// - /// The smart card application ID (AID) to connect to. - /// - /// - /// The connection, if established. `null` otherwise. - /// - /// - /// 'true' if the connection was established, 'false' if there is already an outstanding connection to this - /// device. Note that this method throws exceptions for all other failure modes. - /// - /// - /// The platform device specified in is not a smart-card based, or is not a device - /// capable of selecting arbitrary applications. - /// - public bool TryCreateConnection( - IYubiKeyDevice yubiKeyDevice, - IDevice device, - byte[] applicationId, - [MaybeNullWhen(returnValue: false)] - out IYubiKeyConnection connection) - { - var smartCardDevice = device as ISmartCardDevice ?? throw new ArgumentException( - ExceptionMessages.DeviceDoesNotSupportApplication, - nameof(applicationId)); - - // Since taking a write lock is potentially very expensive, let's try and make a best effort to see if the - // YubiKey is already present. This way we can fail fast. - _hashSetLock.EnterReadLock(); - - try - { - if (_openConnections.Contains(yubiKeyDevice)) - { - connection = null; - - return false; - } - } - finally - { - _hashSetLock.ExitReadLock(); - } - - // The YubiKey wasn't present just a few microseconds ago, so hopefully we will be able to succeed in - // establishing a connection to it. - _hashSetLock.EnterWriteLock(); - - try - { - // We still need to double check that the key wasn't added in the time between exiting the read lock - // and entering the write lock. - if (_openConnections.Contains(yubiKeyDevice)) - { - connection = null; - - return false; - } - - connection = new SmartCardConnection(smartCardDevice, applicationId); - _ = _openConnections.Add(yubiKeyDevice); - } - finally - { - _hashSetLock.ExitWriteLock(); - } - - return true; - } - - /// - /// Ends the tracking of a YubiKey connection. - /// - /// - /// The YubiKey to disconnect from. - /// - /// - /// Thrown if the specified YubiKey does not have any active connections. - /// - public void EndConnection(IYubiKeyDevice yubiKeyDevice) - { - // Since taking a write lock is potentially very expensive, let's try and make a best effort to see if the - // YubiKey is still present. This way we can fail fast. - _hashSetLock.EnterReadLock(); - - try - { - if (!_openConnections.Contains(yubiKeyDevice)) - { - throw new KeyNotFoundException(ExceptionMessages.NoActiveConnections); - } - } - finally - { - _hashSetLock.ExitReadLock(); - } - - _hashSetLock.EnterWriteLock(); - - try - { - if (!_openConnections.Remove(yubiKeyDevice)) - { - throw new KeyNotFoundException(ExceptionMessages.NoActiveConnections); - } - } - finally - { - _hashSetLock.ExitWriteLock(); - } - } - } -} diff --git a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/ConnectionManagerTests.cs b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/ConnectionManagerTests.cs deleted file mode 100644 index 3e8a73eb6..000000000 --- a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/ConnectionManagerTests.cs +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright 2025 Yubico AB -// -// Licensed under the Apache License, Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Collections.Generic; -using NSubstitute; -using Xunit; -using Yubico.Core.Devices; -using Yubico.Core.Devices.Hid; -using Yubico.Core.Devices.SmartCard; -using Yubico.Core.Iso7816; - -namespace Yubico.YubiKey -{ - internal class TestSmartCardDevice : ISmartCardDevice - { - public readonly static ISmartCardDevice AnyInstance = new TestSmartCardDevice() - { Kind = SmartCardConnectionKind.Any }; - - public readonly static ISmartCardDevice NfcInstance = new TestSmartCardDevice() - { Kind = SmartCardConnectionKind.Nfc }; - - public DateTime LastAccessed { get; } = DateTime.Now; - public string Path { get; } = string.Empty; - public string? ParentDeviceId { get; } = null; - public AnswerToReset? Atr { get; } - public SmartCardConnectionKind Kind { get; private set; } - public ISmartCardConnection Connect() - { - throw new System.NotImplementedException(); - } - } - - internal class TestHidDevice : IHidDevice - { - public readonly static IHidDevice FidoInstance = new TestHidDevice() { UsagePage = HidUsagePage.Fido }; - public readonly static IHidDevice KeyboardInstance = new TestHidDevice() { UsagePage = HidUsagePage.Keyboard }; - - public DateTime LastAccessed { get; } = DateTime.Now; - public string Path { get; } = string.Empty; - public string? ParentDeviceId { get; } = null; - public short VendorId { get; } - public short ProductId { get; } - public short Usage { get; } - public HidUsagePage UsagePage { get; private set; } - public IHidConnection ConnectToFeatureReports() - { - throw new System.NotImplementedException(); - } - - public IHidConnection ConnectToIOReports() - { - throw new System.NotImplementedException(); - } - } - - public class ConnectionManagerTests - { - private readonly IYubiKeyDevice _yubiKeyDeviceMock = Substitute.For(); - private readonly ISmartCardDevice _smartCardDeviceMock = Substitute.For(); - private readonly ISmartCardConnection _smartCardConnectionMock = Substitute.For(); - - public static IEnumerable SupportedApplicationTuples => - new List() - { - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.FidoU2f }, - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.Fido2 }, - new object[] { TestHidDevice.KeyboardInstance, YubiKeyApplication.Otp }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.Otp }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.Oath }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.Piv }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.OpenPgp }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.FidoU2f }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.Fido2 }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.Management }, - new object[] { TestSmartCardDevice.AnyInstance, YubiKeyApplication.YubiHsmAuth }, - new object[] { TestSmartCardDevice.NfcInstance, YubiKeyApplication.OtpNdef } - }; - - [Theory] - [MemberData(nameof(SupportedApplicationTuples))] - public void DeviceSupportsApplication_GivenSupportedTuple_ReturnsTrue(IDevice device, YubiKeyApplication application) - { - Assert.True(ConnectionManager.DeviceSupportsApplication(device, application)); - } - - public static IEnumerable UnsupportedApplicationTuples => - new List() - { - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.Otp }, - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.OtpNdef }, - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.Oath }, - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.Piv }, - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.OpenPgp }, - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.Management }, - new object[] { TestHidDevice.FidoInstance, YubiKeyApplication.YubiHsmAuth }, - new object[] { TestHidDevice.KeyboardInstance, YubiKeyApplication.OtpNdef }, - new object[] { TestHidDevice.KeyboardInstance, YubiKeyApplication.Oath }, - new object[] { TestHidDevice.KeyboardInstance, YubiKeyApplication.Piv }, - new object[] { TestHidDevice.KeyboardInstance, YubiKeyApplication.OpenPgp }, - new object[] { TestHidDevice.KeyboardInstance, YubiKeyApplication.Management }, - new object[] { TestHidDevice.KeyboardInstance, YubiKeyApplication.YubiHsmAuth }, - }; - - [Theory] - [MemberData(nameof(UnsupportedApplicationTuples))] - public void DeviceSupportsApplication_GivenUnsupportedTuple_ReturnsFalse(IDevice device, YubiKeyApplication application) - { - Assert.False(ConnectionManager.DeviceSupportsApplication(device, application)); - } - - [Fact] - public void Instance_ReturnsSameInstanceOfConnectionManager() - { - ConnectionManager? connectionManager1 = ConnectionManager.Instance; - Assert.NotNull(connectionManager1); - - ConnectionManager? connectionManager2 = ConnectionManager.Instance; - Assert.Same(connectionManager1, connectionManager2); - } - - [Fact] - public void TryCreateConnection_NoOpenConnections_ReturnsTrueAndConnection() - { - var cm = new ConnectionManager(); - - _ = _smartCardDeviceMock.Connect().Returns(_smartCardConnectionMock); - _ = _smartCardConnectionMock.Transmit(Arg.Any()) - .Returns(new ResponseApdu(Array.Empty(), SWConstants.Success)); - - bool result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - YubiKeyApplication.Piv, - out IYubiKeyConnection? connection); - - Assert.True(result); - Assert.NotNull(connection); - } - - [Fact] - public void TryCreateConnection_OpenConnectionToSameYubiKey_ReturnsFalseAndNull() - { - var cm = new ConnectionManager(); - - _ = _yubiKeyDeviceMock.Equals(Arg.Any()) - .Returns(true); - _ = _smartCardDeviceMock.Connect().Returns(_smartCardConnectionMock); - _ = _smartCardConnectionMock.Transmit(Arg.Any()) - .Returns(new ResponseApdu(Array.Empty(), SWConstants.Success)); - - _ = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - YubiKeyApplication.Piv, - out _); - - bool result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - YubiKeyApplication.Piv, - out IYubiKeyConnection? connection); - - Assert.False(result); - Assert.Null(connection); - } - - [Fact] - public void TryCreateConnection_OpenConnectionToDifferentYubiKey_ReturnsTrueAndConnection() - { - var cm = new ConnectionManager(); - - _ = _yubiKeyDeviceMock.Equals(Arg.Any()) - .Returns(false); - _ = _smartCardDeviceMock.Connect().Returns(_smartCardConnectionMock); - _ = _smartCardConnectionMock.Transmit(Arg.Any()) - .Returns(new ResponseApdu(Array.Empty(), SWConstants.Success)); - - bool result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - YubiKeyApplication.Piv, - out IYubiKeyConnection? connection1); - - Assert.True(result); - Assert.NotNull(connection1); - - result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - YubiKeyApplication.Piv, - out IYubiKeyConnection? connection2); - - Assert.True(result); - Assert.NotNull(connection2); - } - - [Fact] - public void TryCreateConnectionOverload_NoOpenConnections_ReturnsTrueAndConnection() - { - var cm = new ConnectionManager(); - - _ = _smartCardDeviceMock.Connect().Returns(_smartCardConnectionMock); - _ = _smartCardConnectionMock.Transmit(Arg.Any()) - .Returns(new ResponseApdu(Array.Empty(), SWConstants.Success)); - - bool result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - new byte[] { 1, 2, 3, 4 }, - out IYubiKeyConnection? connection); - - Assert.True(result); - Assert.NotNull(connection); - } - - [Fact] - public void TryCreateConnectionOverload_OpenConnectionToSameYubiKey_ReturnsFalseAndNull() - { - var cm = new ConnectionManager(); - - _ = _yubiKeyDeviceMock.Equals(Arg.Any()) - .Returns(true); - _ = _smartCardDeviceMock.Connect().Returns(_smartCardConnectionMock); - _ = _smartCardConnectionMock.Transmit(Arg.Any()) - .Returns(new ResponseApdu(Array.Empty(), SWConstants.Success)); - - _ = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - new byte[] { 1, 2, 3, 4 }, - out _); - - bool result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - new byte[] { 1, 2, 3, 4 }, - out IYubiKeyConnection? connection); - - Assert.False(result); - Assert.Null(connection); - } - - [Fact] - public void TryCreateConnectionOverload_OpenConnectionToDifferentYubiKey_ReturnsTrueAndConnection() - { - var cm = new ConnectionManager(); - - _ = _yubiKeyDeviceMock.Equals(Arg.Any()) - .Returns(false); - _ = _smartCardDeviceMock.Connect().Returns(_smartCardConnectionMock); - _ = _smartCardConnectionMock.Transmit(Arg.Any()) - .Returns(new ResponseApdu(Array.Empty(), SWConstants.Success)); - - bool result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - new byte[] { 1, 2, 3, 4 }, - out IYubiKeyConnection? connection1); - - Assert.True(result); - Assert.NotNull(connection1); - - result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - new byte[] { 1, 2, 3, 4 }, - out IYubiKeyConnection? connection2); - - Assert.True(result); - Assert.NotNull(connection2); - } - - [Fact] - public void EndConnection_NoOpenConnections_ThrowsNotFoundException() - { - var cm = new ConnectionManager(); - - void Action() => cm.EndConnection(_yubiKeyDeviceMock); - - _ = Assert.Throws(Action); - } - - [Fact] - public void EndConnection_OpenConnectionToSameYubiKey_AllowsNewConnection() - { - var cm = new ConnectionManager(); - - _ = _yubiKeyDeviceMock.Equals(Arg.Any()) - .Returns(true); - _ = _smartCardDeviceMock.Connect().Returns(_smartCardConnectionMock); - _ = _smartCardConnectionMock.Transmit(Arg.Any()) - .Returns(new ResponseApdu(Array.Empty(), SWConstants.Success)); - - _ = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - YubiKeyApplication.Piv, - out _); - - cm.EndConnection(_yubiKeyDeviceMock); - - bool result = cm.TryCreateConnection( - _yubiKeyDeviceMock, - _smartCardDeviceMock, - YubiKeyApplication.Piv, - out IYubiKeyConnection? connection); - - Assert.True(result); - Assert.NotNull(connection); - } - } -} From 3beb02a6695330190a31bc1756912aed17252a02 Mon Sep 17 00:00:00 2001 From: Dennis Dyall Date: Thu, 18 Dec 2025 11:42:08 +0100 Subject: [PATCH 30/50] refactor: streamline extension handling and improve variable declarations --- .../SmartCard/DesktopSmartCardConnection.cs | 4 +- .../Fido2/AuthenticatorOperationParameters.cs | 37 +++---------------- .../YubiKey/Fido2/Fido2Session.LargeBlobs.cs | 3 +- 3 files changed, 9 insertions(+), 35 deletions(-) diff --git a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs index fd989196c..f8a6f1935 100644 --- a/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs +++ b/Yubico.Core/src/Yubico/Core/Devices/SmartCard/DesktopSmartCardConnection.cs @@ -146,11 +146,11 @@ public ResponseApdu Transmit(CommandApdu commandApdu) // The YubiKey likely will never return a buffer larger than 512 bytes without instead // using response chaining. byte[] outputBuffer = new byte[512]; - + byte[] apduBytes = commandApdu.AsByteArray(); uint result = SCardTransmit( _cardHandle, new SCARD_IO_REQUEST(_activeProtocol), - commandApdu.AsByteArray(), + apduBytes, IntPtr.Zero, outputBuffer, out int outputBufferSize diff --git a/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/AuthenticatorOperationParameters.cs b/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/AuthenticatorOperationParameters.cs index 599305369..856fafa98 100644 --- a/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/AuthenticatorOperationParameters.cs +++ b/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/AuthenticatorOperationParameters.cs @@ -80,8 +80,8 @@ public abstract class AuthenticatorOperationParameters : I /// public void AddExtension(string extensionKey, TValue value) { - Guard.IsNotNullOrWhiteSpace(extensionKey, nameof(extensionKey)); - Guard.IsNotNull(value, nameof(value)); + Guard.IsNotNullOrWhiteSpace(extensionKey); + Guard.IsNotNull(value); _extensions[extensionKey] = value switch { @@ -95,7 +95,9 @@ public void AddExtension(string extensionKey, TValue value) ICborEncode cborEncode => cborEncode.CborEncode(), _ => throw new ArgumentException(ExceptionMessages.Ctap2CborUnexpectedValue, nameof(value)) }; - + + return; + static byte[] EncodeValue(Action writeAction) { var cbor = new CborWriter(CborConformanceMode.Ctap2Canonical, convertIndefiniteLengthEncodings: true); @@ -103,34 +105,7 @@ static byte[] EncodeValue(Action writeAction) return cbor.Encode(); } } - - /// - /// Add an entry to the extensions list. - /// - /// - /// - /// Each extension is a key/value pair. For each extension the key is a - /// string (such as "credProtect" or "hmac-secret"). However, each value - /// is different. There will be a definition of the value that - /// goes with each key. It will be possible to encode that definition - /// using the rules of CBOR. The caller supplies the key and the encoded value. - /// - /// - /// - /// The key of key/value to add. - /// - /// - /// The CBOR-encoded value of key/value to add. - /// - /// - /// The extensionKey or encodedValue arg is null. - /// - public void AddExtension(string extensionKey, byte[] encodedBytes) - { - Guard.IsNotNull(encodedBytes, nameof(encodedBytes)); - _extensions[extensionKey] = encodedBytes; - } - + /// /// Add an entry to the list of options. /// diff --git a/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/Fido2Session.LargeBlobs.cs b/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/Fido2Session.LargeBlobs.cs index b53873494..671564a95 100644 --- a/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/Fido2Session.LargeBlobs.cs +++ b/Yubico.YubiKey/src/Yubico/YubiKey/Fido2/Fido2Session.LargeBlobs.cs @@ -236,7 +236,6 @@ public void SetSerializedLargeBlobArray(SerializedLargeBlobArray serializedLarge int remaining = encodedArray.Length; int maxFragmentLength = AuthenticatorInfo.MaximumMessageSize ?? AuthenticatorInfo.DefaultMaximumMessageSize; maxFragmentLength -= MessageOverhead; - int currentLength; bool forceToken = false; using HashAlgorithm digester = CryptographyProviders.Sha256Creator(); @@ -247,7 +246,7 @@ public void SetSerializedLargeBlobArray(SerializedLargeBlobArray serializedLarge forceToken, PinUvAuthTokenPermissions.LargeBlobWrite, null); currentToken.CopyTo(token.AsMemory()); - currentLength = remaining >= maxFragmentLength ? maxFragmentLength : remaining; + int currentLength = remaining >= maxFragmentLength ? maxFragmentLength : remaining; byte[] dataToAuth = BuildDataToAuth(encodedArray, offset, currentLength, digester); byte[] pinUvAuthParam = AuthProtocol.AuthenticateUsingPinToken(token, 0, currentToken.Length, dataToAuth); From 625de2d931ab99ed9a792a04d19e5ceeb6ebf2b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Dec 2025 08:11:55 +0000 Subject: [PATCH 31/50] build(deps): bump the github-actions group across 1 directory with 6 updates Bumps the github-actions group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `5.0.0` | `6.0.0` | | [actions/download-artifact](https://github.com/actions/download-artifact) | `6.0.0` | `7.0.0` | | [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) | `3.0.0` | `3.1.0` | | [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) | `1.0.23` | `1.0.27` | | [github/codeql-action](https://github.com/github/codeql-action) | `4.31.7` | `4.31.9` | | [EnricoMi/publish-unit-test-result-action](https://github.com/enricomi/publish-unit-test-result-action) | `2.21.0` | `2.22.0` | Updates `actions/upload-artifact` from 5.0.0 to 6.0.0 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f) Updates `actions/download-artifact` from 6.0.0 to 7.0.0 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/018cc2cf5baa6db3ef3c5f8a56943fffe632ef53...37930b1c2abaa49bbe596cd826c3c89aef350131) Updates `actions/attest-build-provenance` from 3.0.0 to 3.1.0 - [Release notes](https://github.com/actions/attest-build-provenance/releases) - [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md) - [Commits](https://github.com/actions/attest-build-provenance/compare/977bb373ede98d70efdf65b84cb5f73e068dcc2a...00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8) Updates `anthropics/claude-code-action` from 1.0.23 to 1.0.27 - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](https://github.com/anthropics/claude-code-action/compare/f0c8eb29807907de7f5412d04afceb5e24817127...7145c3e0510bcdbdd29f67cc4a8c1958f1acfa2f) Updates `github/codeql-action` from 4.31.7 to 4.31.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/cf1bb45a277cb3c205638b2cd5c984db1c46a412...5d4e8d1aca955e8d8589aabd499c5cae939e33c7) Updates `EnricoMi/publish-unit-test-result-action` from 2.21.0 to 2.22.0 - [Release notes](https://github.com/enricomi/publish-unit-test-result-action/releases) - [Commits](https://github.com/enricomi/publish-unit-test-result-action/compare/34d7c956a59aed1bfebf31df77b8de55db9bbaaf...27d65e188ec43221b20d26de30f4892fad91df2f) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/download-artifact dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/attest-build-provenance dependency-version: 3.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: anthropics/claude-code-action dependency-version: 1.0.27 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action dependency-version: 4.31.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: EnricoMi/publish-unit-test-result-action dependency-version: 2.22.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-nativeshims.yml | 26 +++++++++++------------ .github/workflows/build-pull-requests.yml | 4 ++-- .github/workflows/build.yml | 14 ++++++------ .github/workflows/claude.yml | 2 +- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/scorecard.yml | 4 ++-- .github/workflows/test-macos.yml | 2 +- .github/workflows/test-ubuntu.yml | 2 +- .github/workflows/test-windows.yml | 2 +- .github/workflows/test.yml | 14 ++++++------ .github/workflows/upload-docs.yml | 2 +- 11 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build-nativeshims.yml b/.github/workflows/build-nativeshims.yml index 1fe116b1c..b3357f4cb 100644 --- a/.github/workflows/build-nativeshims.yml +++ b/.github/workflows/build-nativeshims.yml @@ -60,25 +60,25 @@ jobs: } else { & ./build-windows.ps1 } - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: win-x64 path: Yubico.NativeShims/win-x64/** - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: win-x86 path: Yubico.NativeShims/win-x86/** - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: win-arm64 path: Yubico.NativeShims/win-arm64/** - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: nuspec path: | Yubico.NativeShims/*.nuspec Yubico.NativeShims/readme.md - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: msbuild path: Yubico.NativeShims/msbuild/* @@ -235,7 +235,7 @@ jobs: readelf -V *.so | grep GLIBC_2 | sort -u echo "✅ Binary compatible with Debian 10 (glibc 2.28)" ' - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: linux-x64 path: Yubico.NativeShims/linux-x64/*.so @@ -396,7 +396,7 @@ jobs: readelf -V *.so | grep GLIBC_2 | sort -u echo "✅ ARM64 binary compatible with Debian 10 (glibc 2.28)" ' - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: linux-arm64 path: Yubico.NativeShims/linux-arm64/*.so @@ -422,11 +422,11 @@ jobs: else sh ./build-macOS.sh fi - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: osx-x64 path: Yubico.NativeShims/osx-x64/** - - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: osx-arm64 path: Yubico.NativeShims/osx-arm64/** @@ -450,7 +450,7 @@ jobs: egress-policy: audit - name: Download contents, set metadata and package - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - run: | mv nuspec/*.nuspec . mv nuspec/readme.md . @@ -465,13 +465,13 @@ jobs: - run: nuget pack Yubico.NativeShims.nuspec - name: Upload Nuget Package - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: NuGet Package NativeShims path: Yubico.NativeShims.*.nupkg - name: Generate artifact attestation - uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 + uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 with: subject-path: | Yubico.NativeShims/**/*.dll @@ -493,7 +493,7 @@ jobs: with: egress-policy: audit - - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: NuGet Package NativeShims - run: | diff --git a/.github/workflows/build-pull-requests.yml b/.github/workflows/build-pull-requests.yml index 5feb4774d..c8f7c7dbd 100644 --- a/.github/workflows/build-pull-requests.yml +++ b/.github/workflows/build-pull-requests.yml @@ -68,7 +68,7 @@ jobs: NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Save build artifacts - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: Nuget Packages Release path: | @@ -76,7 +76,7 @@ jobs: Yubico.YubiKey/src/bin/Release/*.nupkg - name: Save build artifacts - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: Assemblies Release path: | diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d43f6b74..6dc419de7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -117,7 +117,7 @@ jobs: # Upload documentation log - name: "Save build artifacts: Docs log" id: docs-log-upload - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: Documentation log path: docfx.log @@ -126,7 +126,7 @@ jobs: # Upload documentation - name: "Save build artifacts: Docs" id: docs-upload - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: Documentation path: docs/_site/ @@ -135,7 +135,7 @@ jobs: # Upload NuGet packages - name: "Save build artifacts: Nuget Packages" id: nuget-upload - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: Nuget Packages path: | @@ -146,7 +146,7 @@ jobs: # Upload symbols - name: "Save build artifacts: Symbols Packages" id: symbols-upload - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: Symbols Packages path: | @@ -157,7 +157,7 @@ jobs: # Upload assemblies - name: "Save build artifacts: Assemblies" id: assemblies-upload - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: Assemblies path: | @@ -167,7 +167,7 @@ jobs: # Generate artifact attestation - name: Generate artifact attestation - uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 + uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 with: subject-path: | Yubico.Core/src/bin/Release/*.nupkg @@ -200,7 +200,7 @@ jobs: with: egress-policy: audit - - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: Nuget Packages - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index a04944e5c..aa4180fdf 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -41,7 +41,7 @@ jobs: - name: Run Claude Code id: claude - uses: anthropics/claude-code-action@f0c8eb29807907de7f5412d04afceb5e24817127 # v1.0.23 + uses: anthropics/claude-code-action@7145c3e0510bcdbdd29f67cc4a8c1958f1acfa2f # v1.0.27 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c936a588c..62f31eb81 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -74,7 +74,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: # Override automatic language detection to only analyze C# # C/C++ code in Yubico.NativeShims is built separately (requires CMake/vcpkg) @@ -87,4 +87,4 @@ jobs: NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index e13cfa30b..5efb2c88f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -70,7 +70,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: SARIF file path: results.sarif @@ -79,6 +79,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: sarif_file: results.sarif diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index ebb53a304..2fff959c0 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -71,7 +71,7 @@ jobs: run: dotnet test Yubico.Core/tests/Yubico.Core.UnitTests.csproj --filter "FullyQualifiedName!~DisposalTests" --logger trx --settings coverlet.runsettings.xml --collect:"XPlat Code Coverage" - name: Upload Test Result Files - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: TestResults-macOS path: '**/TestResults/*' diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 17860d1c0..aa120d6c2 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -57,7 +57,7 @@ jobs: run: dotnet test Yubico.Core/tests/Yubico.Core.UnitTests.csproj --logger trx --settings coverlet.runsettings.xml --collect:"XPlat Code Coverage" - name: Upload Test Result Files - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: TestResults-Ubuntu path: '**/TestResults/*' diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index ba502f6d2..af483bfab 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -52,7 +52,7 @@ jobs: run: dotnet test Yubico.Core/tests/Yubico.Core.UnitTests.csproj --logger trx --settings coverlet.runsettings.xml --collect:"XPlat Code Coverage" - name: Upload Test Result Files - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: TestResults-Windows path: '**/TestResults/*' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3ef7727f8..bbca12166 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -87,7 +87,7 @@ jobs: with: egress-policy: audit - - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - name: Combine Coverage Reports # This is because one report is produced per project, and we want one result for all of them. uses: danielpalme/ReportGenerator-GitHub-Action@ee0ae774f6d3afedcbd1683c1ab21b83670bdf8e # 5.5.1 with: @@ -114,7 +114,7 @@ jobs: thresholds: "40 60" - name: Upload Code Coverage Report - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: CoverageResults path: code-coverage-results.md @@ -132,7 +132,7 @@ jobs: egress-policy: audit - name: Download coverage results - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: CoverageResults @@ -154,22 +154,22 @@ jobs: with: egress-policy: audit - - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - name: "Add PR Comment: Test Results (Windows)" - uses: EnricoMi/publish-unit-test-result-action@34d7c956a59aed1bfebf31df77b8de55db9bbaaf # v2.21.0 + uses: EnricoMi/publish-unit-test-result-action@27d65e188ec43221b20d26de30f4892fad91df2f # v2.22.0 with: trx_files: "${{ github.workspace }}/TestResults-Windows/**/*.trx" check_name: "Test Results: Windows" - name: "Add PR Comment: Test Results (Ubuntu)" - uses: EnricoMi/publish-unit-test-result-action@34d7c956a59aed1bfebf31df77b8de55db9bbaaf # v2.21.0 + uses: EnricoMi/publish-unit-test-result-action@27d65e188ec43221b20d26de30f4892fad91df2f # v2.22.0 with: trx_files: "${{ github.workspace }}/TestResults-Ubuntu/**/*.trx" check_name: "Test Results: Ubuntu" - name: "Add PR Comment: Test Results (MacOS)" - uses: EnricoMi/publish-unit-test-result-action@34d7c956a59aed1bfebf31df77b8de55db9bbaaf # v2.21.0 + uses: EnricoMi/publish-unit-test-result-action@27d65e188ec43221b20d26de30f4892fad91df2f # v2.22.0 with: trx_files: "${{ github.workspace }}/TestResults-macOS/**/*.trx" check_name: "Test Results: MacOS" \ No newline at end of file diff --git a/.github/workflows/upload-docs.yml b/.github/workflows/upload-docs.yml index 28847cafa..765aaccfa 100644 --- a/.github/workflows/upload-docs.yml +++ b/.github/workflows/upload-docs.yml @@ -54,7 +54,7 @@ jobs: persist-credentials: false # Grab the just-built documentation artifact and inflate the archive at the expected location. - - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: Documentation path: docs/_site/ From a0bd0f11cb3741ade57a8125edff4a4d776fe27d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 08:08:23 +0000 Subject: [PATCH 32/50] Bump Microsoft.CodeAnalysis.NetAnalyzers and 3 others Bumps Microsoft.CodeAnalysis.NetAnalyzers from 10.0.100 to 10.0.101 Bumps Microsoft.Extensions.Configuration.Json from 10.0.0 to 10.0.1 Bumps Microsoft.Extensions.Logging.Abstractions from 10.0.0 to 10.0.1 Bumps Microsoft.Extensions.Options.ConfigurationExtensions from 10.0.0 to 10.0.1 --- updated-dependencies: - dependency-name: Microsoft.CodeAnalysis.NetAnalyzers dependency-version: 10.0.101 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Options.ConfigurationExtensions dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages ... Signed-off-by: dependabot[bot] --- Yubico.Core/src/Yubico.Core.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Yubico.Core/src/Yubico.Core.csproj b/Yubico.Core/src/Yubico.Core.csproj index 544e1515e..f7f18bcd0 100644 --- a/Yubico.Core/src/Yubico.Core.csproj +++ b/Yubico.Core/src/Yubico.Core.csproj @@ -113,14 +113,14 @@ limitations under the License. --> - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + From fde61518bf98430dc85706b70d190daca69acdf7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 08:11:44 +0000 Subject: [PATCH 33/50] Bump Microsoft.Bcl.AsyncInterfaces and 4 others Bumps Microsoft.Bcl.AsyncInterfaces from 10.0.0 to 10.0.1 Bumps Microsoft.CodeAnalysis.NetAnalyzers from 10.0.100 to 10.0.101 Bumps Microsoft.Extensions.Logging.Abstractions from 10.0.0 to 10.0.1 Bumps System.Formats.Asn1 from 10.0.0 to 10.0.1 Bumps System.Formats.Cbor from 10.0.0 to 10.0.1 --- updated-dependencies: - dependency-name: Microsoft.Bcl.AsyncInterfaces dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.CodeAnalysis.NetAnalyzers dependency-version: 10.0.101 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: System.Formats.Asn1 dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: System.Formats.Cbor dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages ... Signed-off-by: dependabot[bot] --- Yubico.YubiKey/src/Yubico.YubiKey.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Yubico.YubiKey/src/Yubico.YubiKey.csproj b/Yubico.YubiKey/src/Yubico.YubiKey.csproj index 6549865c3..c2c55ca92 100644 --- a/Yubico.YubiKey/src/Yubico.YubiKey.csproj +++ b/Yubico.YubiKey/src/Yubico.YubiKey.csproj @@ -104,13 +104,13 @@ limitations under the License. --> - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -123,10 +123,10 @@ limitations under the License. --> all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + From 4db5570ef25628bc1e1c8dc1f9aa9365c0fb0479 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 08:14:19 +0000 Subject: [PATCH 34/50] Bump Microsoft.Bcl.Cryptography and 3 others Bumps Microsoft.Bcl.Cryptography from 10.0.0 to 10.0.1 Bumps Microsoft.NET.Test.Sdk from 18.0.0 to 18.0.1 Bumps System.Formats.Asn1 from 10.0.0 to 10.0.1 Bumps Xunit.SkippableFact from 1.5.23 to 1.5.61 --- updated-dependencies: - dependency-name: Microsoft.Bcl.Cryptography dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: System.Formats.Asn1 dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.NET.Test.Sdk dependency-version: 18.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Xunit.SkippableFact dependency-version: 1.5.61 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages ... Signed-off-by: dependabot[bot] --- .../integration/Yubico.YubiKey.IntegrationTests.csproj | 8 ++++---- Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj | 4 ++-- .../tests/utilities/Yubico.YubiKey.TestUtilities.csproj | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj index 991101245..ce1d09211 100644 --- a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj +++ b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj @@ -32,10 +32,10 @@ limitations under the License. --> - + - - + + @@ -46,7 +46,7 @@ limitations under the License. --> - + diff --git a/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj b/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj index 9d8971aec..b6bf5a1bf 100644 --- a/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj +++ b/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj @@ -37,12 +37,12 @@ limitations under the License. --> - + - + PreserveNewest diff --git a/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj b/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj index 92975a931..7cfc6bd05 100644 --- a/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj +++ b/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj @@ -31,9 +31,9 @@ limitations under the License. --> - + - + From d544f58c09a03b302377b5d7e62dfa11589368ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 08:15:22 +0000 Subject: [PATCH 35/50] Bump Serilog.Sinks.Console and System.Configuration.ConfigurationManager Bumps Serilog.Sinks.Console from 6.0.0 to 6.1.1 Bumps System.Configuration.ConfigurationManager from 10.0.0 to 10.0.1 --- updated-dependencies: - dependency-name: Serilog.Sinks.Console dependency-version: 6.1.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all_packages - dependency-name: System.Configuration.ConfigurationManager dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages ... Signed-off-by: dependabot[bot] --- Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj index 2800bcbf9..5c58d90fa 100644 --- a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj +++ b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj @@ -35,8 +35,8 @@ limitations under the License. --> - - + + From ed27e313efc3327b9ecc17664bd1d215e8767933 Mon Sep 17 00:00:00 2001 From: Dennis Dyall Date: Wed, 7 Jan 2026 12:11:50 +0100 Subject: [PATCH 36/50] refactor: apply least privilege principle to workflow permissions Move write permissions from top-level to job-level scope to follow security best practices. This ensures each job only has the minimum permissions needed to perform its specific tasks. Changes: - build-pull-requests.yml: Move checks/pull-requests write to run-tests job - test.yml: Move checks/pull-requests write to specific PR comment jobs - codeql-analysis.yml: Move security-events write to analyze job - build.yml: Add explanatory comments for existing job-level permissions - claude.yml: Add explanatory comments for required write permissions --- .github/workflows/build-pull-requests.yml | 11 +++++++---- .github/workflows/build.yml | 16 ++++++++++------ .github/workflows/claude.yml | 11 ++++++----- .github/workflows/codeql-analysis.yml | 12 ++++++------ .github/workflows/test.yml | 22 ++++++++++++++-------- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/.github/workflows/build-pull-requests.yml b/.github/workflows/build-pull-requests.yml index 5feb4774d..4b92f3f3d 100644 --- a/.github/workflows/build-pull-requests.yml +++ b/.github/workflows/build-pull-requests.yml @@ -29,14 +29,17 @@ on: - '.github/workflows/build-pull-requests.yml' permissions: - pull-requests: write - checks: write contents: read - packages: read - + jobs: run-tests: name: Run tests + # Requires write permissions to publish test results and coverage reports to PR + permissions: + pull-requests: write # Required to comment on PRs with test results + checks: write # Required to create check runs for test results + contents: read + packages: read uses: ./.github/workflows/test.yml with: build-coverage-report: true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d43f6b74..802b55298 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,11 +54,12 @@ permissions: jobs: run-tests: name: Run tests + # Requires write permissions to publish test results permissions: - checks: write + checks: write # Required to create check runs for test results + pull-requests: write # Required to comment on PRs with test results contents: read packages: read - pull-requests: write uses: ./.github/workflows/test.yml with: build-coverage-report: false @@ -67,11 +68,12 @@ jobs: name: Build artifacts runs-on: windows-2022 needs: run-tests + # Requires write permissions to generate artifact attestations permissions: - id-token: write + id-token: write # Required for OIDC token generation + attestations: write # Required to attest build provenance contents: read packages: read - attestations: write outputs: docs-log-id: ${{ steps.docs-log-upload.outputs.artifact-id }} docs-id: ${{ steps.docs-upload.outputs.artifact-id }} @@ -180,8 +182,9 @@ jobs: upload-docs: name: Upload docs if: ${{ github.event.inputs.push-to-docs == 'true' }} + # Requires write permission for OIDC authentication to GCP permissions: - id-token: write + id-token: write # Required for OIDC token generation contents: read uses: ./.github/workflows/upload-docs.yml needs: build-artifacts @@ -191,9 +194,10 @@ jobs: runs-on: windows-2022 needs: build-artifacts if: ${{ github.event.inputs.push-to-dev == 'true' }} + # Requires write permission to publish NuGet packages permissions: + packages: write # Required to publish to GitHub Packages contents: read - packages: write steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index a04944e5c..af6156ce2 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -21,12 +21,13 @@ jobs: (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) runs-on: ubuntu-latest + # Requires write permissions for Claude Code to interact with repository permissions: - contents: write - pull-requests: write - issues: write - id-token: write - actions: read # Required for Claude to read CI results on PRs + contents: write # Required for Claude to commit/push changes + pull-requests: write # Required to comment on and manage PRs + issues: write # Required to comment on and manage issues + id-token: write # Required for OIDC token generation + actions: read # Required for Claude to read CI results on PRs steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c936a588c..fd088c3d1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -40,18 +40,18 @@ on: - '.github/workflows/*.yml' permissions: - # required for all workflows - security-events: write - - # only required for workflows in private repositories - actions: read contents: read - packages: read jobs: analyze: name: Analyze runs-on: windows-2022 + # Requires write permission to upload CodeQL security scan results + permissions: + security-events: write # Required for CodeQL to upload scan results + actions: read # Required for workflows in private repositories + contents: read + packages: read steps: - name: Harden the runner (Audit all outbound calls) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3ef7727f8..5b2c7b612 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,11 +59,8 @@ on: # - '.github/workflows/test.yml' permissions: - pull-requests: write contents: read - checks: write - packages: read - + jobs: test-windows: name: Tests @@ -119,10 +116,14 @@ jobs: name: CoverageResults path: code-coverage-results.md - pr-comment-coverage-results: + pr-comment-coverage-results: name: "Add PR Comment: Coverage Results" runs-on: ubuntu-latest - needs: build-coverage-report + needs: build-coverage-report + # Requires write permission to comment on PRs with coverage results + permissions: + pull-requests: write # Required to add/update PR comments + contents: read if: github.event_name == 'pull_request' steps: @@ -142,10 +143,15 @@ jobs: recreate: true path: code-coverage-results.md - pr-comment-test-results: + pr-comment-test-results: name: "Add PR Comment: Test Results" runs-on: ubuntu-latest - needs: [test-windows, test-ubuntu, test-macos] + needs: [test-windows, test-ubuntu, test-macos] + # Requires write permissions to publish test results to PR + permissions: + checks: write # Required to create check runs for test results + pull-requests: write # Required to add/update PR comments + contents: read if: github.event_name == 'pull_request' steps: From 98b7bfd1390b2155d6575f997537cf0942e13b8f Mon Sep 17 00:00:00 2001 From: Dennis Dyall Date: Wed, 7 Jan 2026 12:30:00 +0100 Subject: [PATCH 37/50] feat: enable branch protection check in scorecard workflow Uncomment repo_token configuration to enable the Branch-Protection check. This requires a fine-grained PAT with "Administration: Read-only" permission to be added as a repository secret named SCORECARD_TOKEN. --- .github/workflows/scorecard.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index e13cfa30b..70df8ffa6 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -49,11 +49,11 @@ jobs: with: results_file: results.sarif results_format: sarif - # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecard on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. - # repo_token: ${{ secrets.SCORECARD_TOKEN }} + # Fine-grained PAT token required to enable Branch-Protection check. + # The token must have "Administration: Read-only" permission. + # To create the PAT, follow: https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional + # Add the token as a repository secret named SCORECARD_TOKEN. + repo_token: ${{ secrets.SCORECARD_TOKEN }} # Public repositories: # - Publish results to OpenSSF REST API for easy access by consumers From 85df5aeb90ed7e746822786b424322c735ac2026 Mon Sep 17 00:00:00 2001 From: Dennis Dyallo Date: Wed, 7 Jan 2026 12:50:51 +0100 Subject: [PATCH 38/50] Create SECURITY.md --- SECURITY.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..8ecfe583f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,28 @@ +# Security +Yubico is committed to maintaining the security and privacy of our products, services, and customers. +We value the contributions of the security research community and have implemented a Coordinated Vulnerability +Disclosure process to handle vulnerability disclosures in a manner that protects the community while encouraging +responsible reporting. + +# Reporting Security Issues + +If you believe you have found a security vulnerability in any Yubico-owned repository, **please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests**, instead report it to us as described below. + +* __Email Us__: Send details to **security@yubico.com** . + Include: + - A description of the issue and steps to reproduce it. + - Any supporting evidence (e.g., screenshots, proof of concept). + - Any potential impact and your recommendations for mitigating the risk. + - Your contact information (optional if you wish to remain anonymous). +* __Encrypt Sensitive Data__: + Use our PGP key at __[Yubico-Security-Team-Public-Key](https://www.yubico.com/.well-known/Yubico-Security-Team-Public.asc)__ if needed. +* __Act Responsibly__: We request that you not share information about a potential vulnerability with others until we have had a chance to triage and if needed, provide mitigation to impacted customers. + +# Our Process +* __Confirmation__: We will confirm receipt of the report within 3 business days. +* __Triage__: We will work with you to validate and resolve the issue. +* __Disclosure__: We will notify you when the fix is complete and may coordinate public disclosure timelines, if applicable. +* __Acknowledgement__: If desired, we will acknowledge your contribution as part of the disclosure process. + +# Safe Harbor +Yubico will not pursue or support any legal action related to the research and disclosure of vulnerability when those activities follow Yubico’s coordinated vulnerability disclosure policy and process. From db2ab0ef398560d77eb85607a25243c2011c427e Mon Sep 17 00:00:00 2001 From: Dennis Dyall Date: Wed, 7 Jan 2026 15:02:03 +0100 Subject: [PATCH 39/50] fix: restore packages read permission for reusable test workflows Add packages: read to top-level permissions in test.yml. This permission is required by the reusable test workflows (test-windows.yml, test-ubuntu.yml, test-macos.yml) to access GitHub Packages for NuGet dependencies. --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9e7edcc3d..cd74b1873 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -60,6 +60,7 @@ on: permissions: contents: read + packages: read # Required by reusable test workflows to access GitHub Packages jobs: test-windows: From 836ce8cbd3216ff48a3922599bfa9ce368349264 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 08:16:37 +0000 Subject: [PATCH 40/50] chore(deps): bump nginx from `052b75a` to `66d420c` Bumps nginx from `052b75a` to `66d420c`. --- updated-dependencies: - dependency-name: nginx dependency-version: alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 14510c395..0c51f5df6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM nginx:alpine@sha256:052b75ab72f690f33debaa51c7e08d9b969a0447a133eb2b99cc905d9188cb2b +FROM nginx:alpine@sha256:66d420cc54ef85bcc1d72220e83d7aaa6c4850bd2904794e3a56f09fd4ccb66e ARG UID=1000 ARG GID=1000 From 64c4d684e34bbfd00a6bd73504350ec19bd67a2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 08:18:49 +0000 Subject: [PATCH 41/50] chore(deps): bump the github-actions group with 3 updates Bumps the github-actions group with 3 updates: [actions/setup-dotnet](https://github.com/actions/setup-dotnet), [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) and [github/codeql-action](https://github.com/github/codeql-action). Updates `actions/setup-dotnet` from 5.0.1 to 5.1.0 - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](https://github.com/actions/setup-dotnet/compare/2016bd2012dba4e32de620c46fe006a3ac9f0602...baa11fbfe1d6520db94683bd5c7a3818018e4309) Updates `anthropics/claude-code-action` from 1.0.27 to 1.0.29 - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](https://github.com/anthropics/claude-code-action/compare/7145c3e0510bcdbdd29f67cc4a8c1958f1acfa2f...1b8ee3b94104046d71fde52ec3557651ad8c0d71) Updates `github/codeql-action` from 4.31.9 to 4.31.10 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5d4e8d1aca955e8d8589aabd499c5cae939e33c7...cdefb33c0f6224e58673d9004f47f7cb3e328b89) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-version: 5.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: anthropics/claude-code-action dependency-version: 1.0.29 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action dependency-version: 4.31.10 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-pull-requests.yml | 2 +- .github/workflows/build.yml | 4 ++-- .github/workflows/claude.yml | 2 +- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecard.yml | 2 +- .github/workflows/test-macos.yml | 2 +- .github/workflows/test-ubuntu.yml | 2 +- .github/workflows/test-windows.yml | 2 +- .github/workflows/verify-code-style.yml | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-pull-requests.yml b/.github/workflows/build-pull-requests.yml index 81f687d95..ee2d2a1b6 100644 --- a/.github/workflows/build-pull-requests.yml +++ b/.github/workflows/build-pull-requests.yml @@ -58,7 +58,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: global-json-file: global.json source-url: https://nuget.pkg.github.com/Yubico/index.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index feb504686..aa7a74634 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,7 +89,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: global-json-file: "./global.json" source-url: https://nuget.pkg.github.com/Yubico/index.json @@ -207,7 +207,7 @@ jobs: - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: Nuget Packages - - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: source-url: https://nuget.pkg.github.com/Yubico/index.json env: diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 62cf5da33..f1822e1a7 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -42,7 +42,7 @@ jobs: - name: Run Claude Code id: claude - uses: anthropics/claude-code-action@7145c3e0510bcdbdd29f67cc4a8c1958f1acfa2f # v1.0.27 + uses: anthropics/claude-code-action@1b8ee3b94104046d71fde52ec3557651ad8c0d71 # v1.0.29 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 81e6be8ec..709630840 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -66,7 +66,7 @@ jobs: # Setup .NET with authenticated NuGet source - name: Setup .NET - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: source-url: https://nuget.pkg.github.com/Yubico/index.json env: @@ -74,7 +74,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: # Override automatic language detection to only analyze C# # C/C++ code in Yubico.NativeShims is built separately (requires CMake/vcpkg) @@ -87,4 +87,4 @@ jobs: NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b73360eb6..a650c0be9 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -79,6 +79,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: sarif_file: results.sarif diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index 2fff959c0..a367e631b 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: global-json-file: "./global.json" diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index aa120d6c2..4db006eec 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: global-json-file: "./global.json" diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index af483bfab..74203e16f 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -38,7 +38,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: global-json-file: "./global.json" diff --git a/.github/workflows/verify-code-style.yml b/.github/workflows/verify-code-style.yml index 91ee3afb1..91f20b45e 100644 --- a/.github/workflows/verify-code-style.yml +++ b/.github/workflows/verify-code-style.yml @@ -44,7 +44,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 + - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: global-json-file: "./global.json" source-url: https://nuget.pkg.github.com/Yubico/index.json From 5132c686b8807c68d2b4c9cce8e2e590db0847f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 08:22:33 +0000 Subject: [PATCH 42/50] Bump the all_packages group with 10 updates Bumps Microsoft.Bcl.AsyncInterfaces from 10.0.1 to 10.0.2 Bumps Microsoft.Bcl.Cryptography from 10.0.1 to 10.0.2 Bumps Microsoft.CodeAnalysis.NetAnalyzers from 10.0.101 to 10.0.102 Bumps Microsoft.Extensions.Configuration.Json from 10.0.1 to 10.0.2 Bumps Microsoft.Extensions.Logging.Abstractions from 10.0.1 to 10.0.2 Bumps Microsoft.Extensions.Options.ConfigurationExtensions from 10.0.1 to 10.0.2 Bumps System.Configuration.ConfigurationManager from 10.0.1 to 10.0.2 Bumps System.Formats.Asn1 from 10.0.1 to 10.0.2 Bumps System.Formats.Cbor from 10.0.1 to 10.0.2 Bumps Xunit.SkippableFact from 1.5.23 to 1.5.61 --- updated-dependencies: - dependency-name: Microsoft.Bcl.AsyncInterfaces dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Bcl.Cryptography dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: System.Formats.Asn1 dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.CodeAnalysis.NetAnalyzers dependency-version: 10.0.102 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.CodeAnalysis.NetAnalyzers dependency-version: 10.0.102 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Configuration.Json dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Options.ConfigurationExtensions dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: System.Configuration.ConfigurationManager dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: System.Formats.Asn1 dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: System.Formats.Cbor dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Xunit.SkippableFact dependency-version: 1.5.61 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages ... Signed-off-by: dependabot[bot] --- Yubico.Core/src/Yubico.Core.csproj | 9 +++++---- Yubico.Core/tests/Yubico.Core.UnitTests.csproj | 2 +- Yubico.YubiKey/src/Yubico.YubiKey.csproj | 10 +++++----- .../integration/Yubico.YubiKey.IntegrationTests.csproj | 4 ++-- .../tests/sandbox/Yubico.YubiKey.TestApp.csproj | 2 +- .../tests/unit/Yubico.YubiKey.UnitTests.csproj | 2 +- .../utilities/Yubico.YubiKey.TestUtilities.csproj | 2 +- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Yubico.Core/src/Yubico.Core.csproj b/Yubico.Core/src/Yubico.Core.csproj index f7f18bcd0..1136a1428 100644 --- a/Yubico.Core/src/Yubico.Core.csproj +++ b/Yubico.Core/src/Yubico.Core.csproj @@ -113,14 +113,14 @@ limitations under the License. --> - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + @@ -136,6 +136,7 @@ limitations under the License. --> + <_Parameter1>Yubico.Core.UnitTests,PublicKey=00240000048000001401000006020000002400005253413100080000010001003312c63e1417ad4652242148c599b55c50d3213c7610b4cc1f467b193bfb8d131de6686268a9db307fcef9efcd5e467483fe9015307e5d0cf9d2fd4df12f29a1c7a72e531d8811ca70f6c80c4aeb598c10bb7fc48742ab86aa7986b0ae9a2f4876c61e0b81eb38e5b549f1fc861c633206f5466bfde021cb08d094742922a8258b582c3bc029eab88c98d476dac6e6f60bc0016746293f5337c68b22e528931b6494acddf1c02b9ea3986754716a9f2a32c59ff3d97f1e35ee07ca2972b0269a4cde86f7b64f80e7c13152c0f84083b5cc4f06acc0efb4316ff3f08c79bc0170229007fb27c97fb494b22f9f7b07f45547e263a44d5a7fe7da6a945a5e47afc9 diff --git a/Yubico.Core/tests/Yubico.Core.UnitTests.csproj b/Yubico.Core/tests/Yubico.Core.UnitTests.csproj index ffe5d4959..0a9ce4e91 100644 --- a/Yubico.Core/tests/Yubico.Core.UnitTests.csproj +++ b/Yubico.Core/tests/Yubico.Core.UnitTests.csproj @@ -46,7 +46,7 @@ limitations under the License. --> - + diff --git a/Yubico.YubiKey/src/Yubico.YubiKey.csproj b/Yubico.YubiKey/src/Yubico.YubiKey.csproj index c2c55ca92..dc3d44ef3 100644 --- a/Yubico.YubiKey/src/Yubico.YubiKey.csproj +++ b/Yubico.YubiKey/src/Yubico.YubiKey.csproj @@ -104,13 +104,13 @@ limitations under the License. --> - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -123,10 +123,10 @@ limitations under the License. --> all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj index ce1d09211..0163a5186 100644 --- a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj +++ b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj @@ -32,9 +32,9 @@ limitations under the License. --> - + - + diff --git a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj index 5c58d90fa..f5cd9b9e7 100644 --- a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj +++ b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj @@ -36,7 +36,7 @@ limitations under the License. --> - + diff --git a/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj b/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj index b6bf5a1bf..894414423 100644 --- a/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj +++ b/Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj @@ -42,7 +42,7 @@ limitations under the License. --> - + PreserveNewest diff --git a/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj b/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj index 7cfc6bd05..fe3fd1d5b 100644 --- a/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj +++ b/Yubico.YubiKey/tests/utilities/Yubico.YubiKey.TestUtilities.csproj @@ -31,7 +31,7 @@ limitations under the License. --> - + From 2530e7ae3c8a8e13fff304c4bdbe3e49238a86d1 Mon Sep 17 00:00:00 2001 From: Dennis Dyallo Date: Thu, 22 Jan 2026 15:29:02 +0000 Subject: [PATCH 43/50] fix(sample): Fix YubiKeySignatureGenerator.DigestData regression - Fixed DigestData to use hash digest size instead of key size for RSA keys - Reuses MessageDigestOperations.ComputeMessageDigest for hashing - For RSA: returns raw digest (PadRsa handles signature padding) - For ECC: pads digest to key size with leading zeros if needed - Added unit tests for digest computation logic - Updated devcontainer to include .NET 8.0 and 10.0 --- .devcontainer/devcontainer.json | 7 + .../YubiKeySignatureGenerator.cs | 44 ++-- .../Sample/YubiKeySignatureGeneratorTests.cs | 228 ++++++++++++++++++ issue-395.md | 91 +++++++ 4 files changed, 348 insertions(+), 22 deletions(-) create mode 100644 Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs create mode 100644 issue-395.md diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 16a464a85..f53cf1424 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,13 @@ { "image": "mcr.microsoft.com/devcontainers/dotnet:9.0", + "features": { + "ghcr.io/devcontainers/features/dotnet:2": { + "version": "none", + "additionalVersions": "8.0,10.0" + } + }, + "customizations": { "vscode": { "extensions": [ diff --git a/Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs b/Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs index 55165c0d1..732bb072d 100644 --- a/Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs +++ b/Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs @@ -127,30 +127,28 @@ public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) } // Compute the message digest of the data using the given hashAlgorithm. - private byte[] DigestData(byte[] data, HashAlgorithmName hashAlgorithm) + // For RSA keys, returns the raw digest (PadRsa handles signature padding). + // For ECC keys, pads the digest to key size with leading zeros if needed. + public byte[] DigestData(byte[] data, HashAlgorithmName hashAlgorithm) { - using HashAlgorithm digester = hashAlgorithm.Name switch + byte[] digest = MessageDigestOperations.ComputeMessageDigest(data, hashAlgorithm); + + // For RSA, return the raw digest - PadRsa handles the signature padding + if (_algorithm.IsRSA()) { - "SHA1" => CryptographyProviders.Sha1Creator(), - "SHA256" => CryptographyProviders.Sha256Creator(), - "SHA384" => CryptographyProviders.Sha384Creator(), - "SHA512" => CryptographyProviders.Sha512Creator(), - _ => throw new ArgumentException( - string.Format( - CultureInfo.CurrentCulture, - InvalidAlgorithmMessage)), - }; + return digest; + } - // If the algorithm is P-256, then make sure the digest is exactly 32 - // bytes. If it's P-384, the digest must be exactly 48 bytes. - // We'll prepend 00 bytes if necessary. - int bufferSize = _algorithm.GetKeySizeBytes(); + // For ECC, the digest must match the key size (e.g., 32 bytes for P-256) + // Pad with leading zeros if necessary + int keySizeBytes = _algorithm.GetKeySizeBytes(); - byte[] digest = new byte[bufferSize]; - int offset = bufferSize - (digester.HashSize / 8); + if (digest.Length == keySizeBytes) + { + return digest; + } - // If offset < 0, that means the digest is too big. - if (offset < 0) + if (digest.Length > keySizeBytes) { throw new ArgumentException( string.Format( @@ -158,10 +156,12 @@ private byte[] DigestData(byte[] data, HashAlgorithmName hashAlgorithm) InvalidAlgorithmMessage)); } - _ = digester.TransformFinalBlock(data, 0, data.Length); - Array.Copy(digester.Hash, 0, digest, offset, digest.Length); + // Pad with leading zeros + byte[] paddedDigest = new byte[keySizeBytes]; + int offset = keySizeBytes - digest.Length; + Array.Copy(digest, 0, paddedDigest, offset, digest.Length); - return digest; + return paddedDigest; } // Create a block of data that is the data to sign padded following the diff --git a/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs new file mode 100644 index 000000000..235ad31cb --- /dev/null +++ b/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs @@ -0,0 +1,228 @@ +// Copyright 2025 Yubico AB +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Security.Cryptography; +using Xunit; +using Yubico.YubiKey.Cryptography; + +namespace Yubico.YubiKey.Sample +{ + /// + /// Unit tests for YubiKeySignatureGenerator.DigestData logic. + /// These tests verify the fix for the regression introduced in commit 01d2a667 + /// where _algorithm.GetKeySizeBytes() was incorrectly used instead of the hash digest size. + /// + /// Since YubiKeySignatureGenerator is in an example project that cannot be referenced + /// from unit tests (strong naming issues), these tests verify the digest computation + /// logic directly using the same approach the fixed code uses. + /// + public class YubiKeySignatureGeneratorDigestDataTests + { + private static readonly byte[] TestData = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }; + + /// + /// Computes a digest using the same logic as the fixed YubiKeySignatureGenerator.DigestData method. + /// For RSA: returns the raw digest. + /// For ECC: pads the digest to key size with leading zeros if needed. + /// + private static byte[] ComputeDigestData(byte[] data, HashAlgorithmName hashAlgorithm, KeyType keyType) + { + byte[] digest = ComputeMessageDigest(data, hashAlgorithm); + + // For RSA, return the raw digest - PadRsa handles the signature padding + if (keyType.IsRSA()) + { + return digest; + } + + // For ECC, the digest must match the key size (e.g., 32 bytes for P-256) + // Pad with leading zeros if necessary + int keySizeBytes = keyType.GetKeySizeBytes(); + + if (digest.Length == keySizeBytes) + { + return digest; + } + + if (digest.Length > keySizeBytes) + { + throw new ArgumentException("Digest is larger than key size"); + } + + // Pad with leading zeros + byte[] paddedDigest = new byte[keySizeBytes]; + int offset = keySizeBytes - digest.Length; + Array.Copy(digest, 0, paddedDigest, offset, digest.Length); + + return paddedDigest; + } + + /// + /// Computes a message digest using the same logic as MessageDigestOperations.ComputeMessageDigest. + /// + private static byte[] ComputeMessageDigest(byte[] dataToDigest, HashAlgorithmName hashAlgorithm) + { + using HashAlgorithm digester = hashAlgorithm.Name switch + { + "SHA1" => CryptographyProviders.Sha1Creator(), + "SHA256" => CryptographyProviders.Sha256Creator(), + "SHA384" => CryptographyProviders.Sha384Creator(), + "SHA512" => CryptographyProviders.Sha512Creator(), + _ => throw new ArgumentException("Unsupported algorithm"), + }; + + byte[] digest = new byte[digester.HashSize / 8]; + + _ = digester.TransformFinalBlock(dataToDigest, 0, dataToDigest.Length); + Array.Copy(digester.Hash!, 0, digest, 0, digest.Length); + + return digest; + } + + /// + /// Computes a digest using the OLD BUGGY logic that was in YubiKeySignatureGenerator.DigestData. + /// This is used to verify that the bug would cause failures. + /// + private static byte[] ComputeDigestDataBuggy(byte[] data, HashAlgorithmName hashAlgorithm, KeyType keyType) + { + using HashAlgorithm digester = hashAlgorithm.Name switch + { + "SHA1" => CryptographyProviders.Sha1Creator(), + "SHA256" => CryptographyProviders.Sha256Creator(), + "SHA384" => CryptographyProviders.Sha384Creator(), + "SHA512" => CryptographyProviders.Sha512Creator(), + _ => throw new ArgumentException("Unsupported algorithm"), + }; + + // BUG: This uses key size (256 bytes for RSA2048) instead of digest size (32 bytes for SHA256) + int bufferSize = keyType.GetKeySizeBytes(); + + byte[] digest = new byte[bufferSize]; + int offset = bufferSize - (digester.HashSize / 8); + + if (offset < 0) + { + throw new ArgumentException("Digest too big"); + } + + _ = digester.TransformFinalBlock(data, 0, data.Length); + // BUG: This tries to copy digest.Length (256) bytes from a 32-byte Hash array + Array.Copy(digester.Hash!, 0, digest, offset, digest.Length); + + return digest; + } + + [Theory] + [InlineData(KeyType.RSA2048, "SHA256", 32)] + [InlineData(KeyType.RSA2048, "SHA384", 48)] + [InlineData(KeyType.RSA2048, "SHA512", 64)] + [InlineData(KeyType.RSA1024, "SHA256", 32)] + [InlineData(KeyType.RSA3072, "SHA256", 32)] + [InlineData(KeyType.RSA4096, "SHA256", 32)] + public void DigestData_RSA_ReturnsCorrectDigestSize(KeyType keyType, string hashName, int expectedSize) + { + // Arrange + var hashAlgorithm = new HashAlgorithmName(hashName); + + // Act + byte[] digest = ComputeDigestData(TestData, hashAlgorithm, keyType); + + // Assert + Assert.Equal(expectedSize, digest.Length); + } + + [Fact] + public void DigestData_RSA2048_SHA256_FixedVersion_DoesNotThrow() + { + // This is the specific scenario from the bug report: + // RSA2048 with SHA256 - the fixed version should not throw + var exception = Record.Exception(() => + ComputeDigestData(TestData, HashAlgorithmName.SHA256, KeyType.RSA2048)); + + Assert.Null(exception); + } + + [Fact] + public void DigestData_RSA2048_SHA256_BuggyVersion_Throws() + { + // This demonstrates the bug: RSA2048 with SHA256 was throwing because + // it tried to copy 256 bytes (key size) from a 32-byte array (hash size) + Assert.Throws(() => + ComputeDigestDataBuggy(TestData, HashAlgorithmName.SHA256, KeyType.RSA2048)); + } + + [Theory] + [InlineData(KeyType.ECP256, "SHA256", 32)] // Digest matches key size + [InlineData(KeyType.ECP384, "SHA256", 48)] // Digest (32) padded to key size (48) + [InlineData(KeyType.ECP384, "SHA384", 48)] // Digest matches key size + [InlineData(KeyType.ECP521, "SHA256", 66)] // Digest (32) padded to key size (66) + [InlineData(KeyType.ECP521, "SHA384", 66)] // Digest (48) padded to key size (66) + [InlineData(KeyType.ECP521, "SHA512", 66)] // Digest (64) padded to key size (66) + public void DigestData_ECC_ReturnsCorrectDigestSize(KeyType keyType, string hashName, int expectedSize) + { + // Arrange + var hashAlgorithm = new HashAlgorithmName(hashName); + + // Act + byte[] digest = ComputeDigestData(TestData, hashAlgorithm, keyType); + + // Assert + Assert.Equal(expectedSize, digest.Length); + } + + [Theory] + [InlineData(KeyType.ECP256, "SHA384")] // SHA384 (48 bytes) > P-256 key size (32 bytes) + [InlineData(KeyType.ECP256, "SHA512")] // SHA512 (64 bytes) > P-256 key size (32 bytes) + public void DigestData_ECC_ThrowsWhenDigestLargerThanKeySize(KeyType keyType, string hashName) + { + // Arrange + var hashAlgorithm = new HashAlgorithmName(hashName); + + // Act & Assert + Assert.Throws(() => ComputeDigestData(TestData, hashAlgorithm, keyType)); + } + + [Theory] + [InlineData(KeyType.ECP384, "SHA256", 16)] // P-384 (48) - SHA256 (32) = 16 bytes padding + [InlineData(KeyType.ECP521, "SHA256", 34)] // P-521 (66) - SHA256 (32) = 34 bytes padding + [InlineData(KeyType.ECP521, "SHA384", 18)] // P-521 (66) - SHA384 (48) = 18 bytes padding + public void DigestData_ECC_PadsWithLeadingZeros(KeyType keyType, string hashName, int expectedPadding) + { + // Arrange + var hashAlgorithm = new HashAlgorithmName(hashName); + + // Act + byte[] digest = ComputeDigestData(TestData, hashAlgorithm, keyType); + + // Assert - first bytes should be zeros (padding) + for (int i = 0; i < expectedPadding; i++) + { + Assert.Equal(0, digest[i]); + } + + // The non-zero hash data should start after the padding + bool hasNonZeroData = false; + for (int i = expectedPadding; i < digest.Length; i++) + { + if (digest[i] != 0) + { + hasNonZeroData = true; + break; + } + } + Assert.True(hasNonZeroData, "Expected non-zero hash data after padding"); + } + } +} diff --git a/issue-395.md b/issue-395.md new file mode 100644 index 000000000..7aa02a357 --- /dev/null +++ b/issue-395.md @@ -0,0 +1,91 @@ +# Issue 395: YubiKeySignatureGenerator.DigestData Regression Fix + +## Issue Summary + +**GitHub Issue:** https://github.com/Yubico/Yubico.NET.SDK/issues/395 + +**Problem:** Commit `01d2a667e382e814ce323ed993423d44519c2808` introduced a regression in `YubiKeySignatureGenerator.DigestData` where `_algorithm.GetKeySizeBytes()` was incorrectly used instead of the hash digest size. + +**Symptoms:** +- Running PivSampleCode with RSA2048 key + SHA256 throws `ArgumentException` from `Array.Copy` +- The code tried to copy 256 bytes (RSA2048 key size) from a 32-byte array (SHA256 digest) + +## Root Cause Analysis + +In the buggy code: +```csharp +int bufferSize = _algorithm.GetKeySizeBytes(); // Returns 256 for RSA2048 +byte[] digest = new byte[bufferSize]; // Creates 256-byte buffer +int offset = bufferSize - (digester.HashSize / 8); // 256 - 32 = 224 +// ... +Array.Copy(digester.Hash, 0, digest, offset, digest.Length); // Tries to copy 256 bytes from 32-byte Hash! +``` + +The `GetKeySizeBytes()` returns the **cryptographic key size** (256 bytes for RSA2048), not the **hash digest size** (32 bytes for SHA256). + +## Changes Made + +### 1. Fixed DigestData method +**File:** `Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs` + +- Changed visibility from `private` to `public` (for testing) +- Replaced buggy implementation with call to `MessageDigestOperations.ComputeMessageDigest()` +- **For RSA keys:** Returns the raw digest directly (32/48/64 bytes for SHA256/384/512) +- **For ECC keys:** Pads digest to key size with leading zeros if needed, throws if digest is larger than key size + +### 2. Added Unit Tests +**File:** `Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs` + +Tests cover: +- RSA keys return correct digest sizes (SHA256→32, SHA384→48, SHA512→64 bytes) +- RSA2048+SHA256 fixed version does not throw +- RSA2048+SHA256 buggy version throws (regression test) +- ECC keys pad correctly (P-384+SHA256 → 48 bytes with 16 leading zeros) +- ECC keys throw when digest > key size (P-256+SHA384/512) + +### 3. Updated Dev Container +**File:** `.devcontainer/devcontainer.json` + +Added .NET 8.0 and .NET 10.0 as additional SDK versions to support running tests. + +## Handoff Notes for Next Agent + +### Testing Required +1. **Rebuild the dev container** to get .NET 8.0 runtime: + - Run "Dev Containers: Rebuild Container" from VS Code command palette + +2. **Run unit tests** after container rebuild: + ```bash + dotnet test Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj + ``` + +3. **Manual integration test** (requires YubiKey): + - Run PivSampleCode.exe + - Option 12: GenerateKeyPair → Slot 9A → RSA 2048 → defaults + - Option 18: GetCertRequest → Slot 9A + - Should complete without exception + +### Files Modified +- `.devcontainer/devcontainer.json` - Added .NET 8.0 and 10.0 +- `Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs` - Fixed DigestData +- `Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs` - New test file + +### Branch +`fix/issue-395-digest-data-regression` + +### Cleanup Notes +- The `DigestData` method was made `public` for testing purposes +- Consider reverting to `private` after tests pass, or keep public if useful for users +- The unit tests duplicate the digest logic since PivSampleCode can't be referenced (strong naming) + +### Build Status +- ✅ Main SDK builds successfully +- ✅ PivSampleCode builds successfully +- ⏳ Unit tests not yet run (need .NET 8.0 runtime in container) + +## Related Files + +- Bug report: https://github.com/Yubico/Yubico.NET.SDK/issues/395 +- Breaking commit: `01d2a667e382e814ce323ed993423d44519c2808` +- MessageDigestOperations utility: `Yubico.YubiKey/examples/PivSampleCode/DotNetOperations/MessageDigestOperations.cs` +- KeyDefinitions (key sizes): `Yubico.YubiKey/src/Yubico/YubiKey/Cryptography/KeyDefinitions.cs` From fb4d2083c40f38a0a4d04e50d50c12750a6f40e9 Mon Sep 17 00:00:00 2001 From: Dennis Dyallo Date: Fri, 23 Jan 2026 12:20:08 +0100 Subject: [PATCH 44/50] chore: remove notes --- issue-395.md | 91 ---------------------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 issue-395.md diff --git a/issue-395.md b/issue-395.md deleted file mode 100644 index 7aa02a357..000000000 --- a/issue-395.md +++ /dev/null @@ -1,91 +0,0 @@ -# Issue 395: YubiKeySignatureGenerator.DigestData Regression Fix - -## Issue Summary - -**GitHub Issue:** https://github.com/Yubico/Yubico.NET.SDK/issues/395 - -**Problem:** Commit `01d2a667e382e814ce323ed993423d44519c2808` introduced a regression in `YubiKeySignatureGenerator.DigestData` where `_algorithm.GetKeySizeBytes()` was incorrectly used instead of the hash digest size. - -**Symptoms:** -- Running PivSampleCode with RSA2048 key + SHA256 throws `ArgumentException` from `Array.Copy` -- The code tried to copy 256 bytes (RSA2048 key size) from a 32-byte array (SHA256 digest) - -## Root Cause Analysis - -In the buggy code: -```csharp -int bufferSize = _algorithm.GetKeySizeBytes(); // Returns 256 for RSA2048 -byte[] digest = new byte[bufferSize]; // Creates 256-byte buffer -int offset = bufferSize - (digester.HashSize / 8); // 256 - 32 = 224 -// ... -Array.Copy(digester.Hash, 0, digest, offset, digest.Length); // Tries to copy 256 bytes from 32-byte Hash! -``` - -The `GetKeySizeBytes()` returns the **cryptographic key size** (256 bytes for RSA2048), not the **hash digest size** (32 bytes for SHA256). - -## Changes Made - -### 1. Fixed DigestData method -**File:** `Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs` - -- Changed visibility from `private` to `public` (for testing) -- Replaced buggy implementation with call to `MessageDigestOperations.ComputeMessageDigest()` -- **For RSA keys:** Returns the raw digest directly (32/48/64 bytes for SHA256/384/512) -- **For ECC keys:** Pads digest to key size with leading zeros if needed, throws if digest is larger than key size - -### 2. Added Unit Tests -**File:** `Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs` - -Tests cover: -- RSA keys return correct digest sizes (SHA256→32, SHA384→48, SHA512→64 bytes) -- RSA2048+SHA256 fixed version does not throw -- RSA2048+SHA256 buggy version throws (regression test) -- ECC keys pad correctly (P-384+SHA256 → 48 bytes with 16 leading zeros) -- ECC keys throw when digest > key size (P-256+SHA384/512) - -### 3. Updated Dev Container -**File:** `.devcontainer/devcontainer.json` - -Added .NET 8.0 and .NET 10.0 as additional SDK versions to support running tests. - -## Handoff Notes for Next Agent - -### Testing Required -1. **Rebuild the dev container** to get .NET 8.0 runtime: - - Run "Dev Containers: Rebuild Container" from VS Code command palette - -2. **Run unit tests** after container rebuild: - ```bash - dotnet test Yubico.YubiKey/tests/unit/Yubico.YubiKey.UnitTests.csproj - ``` - -3. **Manual integration test** (requires YubiKey): - - Run PivSampleCode.exe - - Option 12: GenerateKeyPair → Slot 9A → RSA 2048 → defaults - - Option 18: GetCertRequest → Slot 9A - - Should complete without exception - -### Files Modified -- `.devcontainer/devcontainer.json` - Added .NET 8.0 and 10.0 -- `Yubico.YubiKey/examples/PivSampleCode/CertificateOperations/YubiKeySignatureGenerator.cs` - Fixed DigestData -- `Yubico.YubiKey/tests/unit/Yubico/YubiKey/Sample/YubiKeySignatureGeneratorTests.cs` - New test file - -### Branch -`fix/issue-395-digest-data-regression` - -### Cleanup Notes -- The `DigestData` method was made `public` for testing purposes -- Consider reverting to `private` after tests pass, or keep public if useful for users -- The unit tests duplicate the digest logic since PivSampleCode can't be referenced (strong naming) - -### Build Status -- ✅ Main SDK builds successfully -- ✅ PivSampleCode builds successfully -- ⏳ Unit tests not yet run (need .NET 8.0 runtime in container) - -## Related Files - -- Bug report: https://github.com/Yubico/Yubico.NET.SDK/issues/395 -- Breaking commit: `01d2a667e382e814ce323ed993423d44519c2808` -- MessageDigestOperations utility: `Yubico.YubiKey/examples/PivSampleCode/DotNetOperations/MessageDigestOperations.cs` -- KeyDefinitions (key sizes): `Yubico.YubiKey/src/Yubico/YubiKey/Cryptography/KeyDefinitions.cs` From 4f72aaa6a9f3e52a25d550786cb01a23c745afab Mon Sep 17 00:00:00 2001 From: Elena Quijano Date: Fri, 23 Jan 2026 13:14:44 -0800 Subject: [PATCH 45/50] release notes for 1.15.1 --- docs/users-manual/getting-started/whats-new.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/users-manual/getting-started/whats-new.md b/docs/users-manual/getting-started/whats-new.md index 27e8a74dd..9cc321aa2 100644 --- a/docs/users-manual/getting-started/whats-new.md +++ b/docs/users-manual/getting-started/whats-new.md @@ -18,6 +18,18 @@ Here you can find all of the updates and release notes for published versions of ## 1.15.x Releases +### 1.15.1 + +Release date: January 28th, 2026 + +Documentation: + +- The documentation on [PIV certificate sizes](xref:UsersManualPivCertSizes) has been restructured to improve clarity and readability. Additionally, firmware behavior details and practical examples have been added/updated. ([#356](https://github.com/Yubico/Yubico.NET.SDK/pull/356)) + +Dependencies: + +- Several dependencies across integration, unit, and utilities test projects, the test app, and the Yubico.Core and Yubico.YubiKey projects have been updated. ([#388](https://github.com/Yubico/Yubico.NET.SDK/pull/388), [#387](https://github.com/Yubico/Yubico.NET.SDK/pull/387), [#386](https://github.com/Yubico/Yubico.NET.SDK/pull/386), [#384](https://github.com/Yubico/Yubico.NET.SDK/pull/384)) + ### 1.15.0 Release date: December 4th, 2025 From 434417bf2dff22042412b11e94ac2ae518227e5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 08:14:37 +0000 Subject: [PATCH 46/50] chore(deps): bump nginx from `66d420c` to `2622096` Bumps nginx from `66d420c` to `2622096`. --- updated-dependencies: - dependency-name: nginx dependency-version: alpine dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0c51f5df6..90396f3ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM nginx:alpine@sha256:66d420cc54ef85bcc1d72220e83d7aaa6c4850bd2904794e3a56f09fd4ccb66e +FROM nginx:alpine@sha256:2622096d277282954bcf28459f8a3bc527c34ec8f4847fb46ec11f7ed49efd8b ARG UID=1000 ARG GID=1000 From 8e261f04362344254ee40d195ef45bc9ec33b6e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 08:14:38 +0000 Subject: [PATCH 47/50] Bump the all_packages group with 1 update Bumps Microsoft.Extensions.Logging.Console from 10.0.0 to 10.0.2 --- updated-dependencies: - dependency-name: Microsoft.Extensions.Logging.Console dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Logging.Console dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages - dependency-name: Microsoft.Extensions.Logging.Console dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: all_packages ... Signed-off-by: dependabot[bot] --- Yubico.Core/src/Yubico.Core.csproj | 2 +- .../tests/integration/Yubico.YubiKey.IntegrationTests.csproj | 2 +- Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Yubico.Core/src/Yubico.Core.csproj b/Yubico.Core/src/Yubico.Core.csproj index 1136a1428..02744a08e 100644 --- a/Yubico.Core/src/Yubico.Core.csproj +++ b/Yubico.Core/src/Yubico.Core.csproj @@ -119,7 +119,7 @@ limitations under the License. --> - + diff --git a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj index 0163a5186..1f710b871 100644 --- a/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj +++ b/Yubico.YubiKey/tests/integration/Yubico.YubiKey.IntegrationTests.csproj @@ -39,7 +39,7 @@ limitations under the License. --> - + diff --git a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj index f5cd9b9e7..0255a7c8a 100644 --- a/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj +++ b/Yubico.YubiKey/tests/sandbox/Yubico.YubiKey.TestApp.csproj @@ -32,7 +32,7 @@ limitations under the License. --> - + From e81bbd3c458420eaeec1bc759d5abfd1ca57be42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 08:17:27 +0000 Subject: [PATCH 48/50] chore(deps): bump the github-actions group with 5 updates Bumps the github-actions group with 5 updates: | Package | From | To | | --- | --- | --- | | [step-security/harden-runner](https://github.com/step-security/harden-runner) | `2.14.0` | `2.14.1` | | [actions/checkout](https://github.com/actions/checkout) | `6.0.1` | `6.0.2` | | [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) | `3.1.0` | `3.2.0` | | [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) | `1.0.29` | `1.0.37` | | [github/codeql-action](https://github.com/github/codeql-action) | `4.31.10` | `4.32.0` | Updates `step-security/harden-runner` from 2.14.0 to 2.14.1 - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/20cf305ff2072d973412fa9b1e3a4f227bda3c76...e3f713f2d8f53843e71c69a996d56f51aa9adfb9) Updates `actions/checkout` from 6.0.1 to 6.0.2 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd) Updates `actions/attest-build-provenance` from 3.1.0 to 3.2.0 - [Release notes](https://github.com/actions/attest-build-provenance/releases) - [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md) - [Commits](https://github.com/actions/attest-build-provenance/compare/00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8...96278af6caaf10aea03fd8d33a09a777ca52d62f) Updates `anthropics/claude-code-action` from 1.0.29 to 1.0.37 - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](https://github.com/anthropics/claude-code-action/compare/1b8ee3b94104046d71fde52ec3557651ad8c0d71...2817c54db8f44f3a0485d57292566bf07d428a25) Updates `github/codeql-action` from 4.31.10 to 4.32.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/cdefb33c0f6224e58673d9004f47f7cb3e328b89...b20883b0cd1f46c72ae0ba6d1090936928f9fa30) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.14.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/checkout dependency-version: 6.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: actions/attest-build-provenance dependency-version: 3.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: anthropics/claude-code-action dependency-version: 1.0.37 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action dependency-version: 4.32.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-nativeshims.yml | 22 +++++++++++----------- .github/workflows/build-pull-requests.yml | 4 ++-- .github/workflows/build.yml | 10 +++++----- .github/workflows/claude.yml | 6 +++--- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/dependency-review.yml | 4 ++-- .github/workflows/deploy-docs.yml | 10 +++++----- .github/workflows/scorecard.yml | 6 +++--- .github/workflows/test-macos.yml | 4 ++-- .github/workflows/test-ubuntu.yml | 4 ++-- .github/workflows/test-windows.yml | 4 ++-- .github/workflows/test.yml | 6 +++--- .github/workflows/upload-docs.yml | 4 ++-- .github/workflows/verify-code-style.yml | 4 ++-- 14 files changed, 48 insertions(+), 48 deletions(-) diff --git a/.github/workflows/build-nativeshims.yml b/.github/workflows/build-nativeshims.yml index b3357f4cb..428b83f69 100644 --- a/.github/workflows/build-nativeshims.yml +++ b/.github/workflows/build-nativeshims.yml @@ -38,11 +38,11 @@ jobs: runs-on: windows-2022 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - run: | @@ -88,11 +88,11 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Install Zig (pinned version) @@ -245,11 +245,11 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Install Zig (pinned version) @@ -406,11 +406,11 @@ jobs: runs-on: macos-14 steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - run: | @@ -445,7 +445,7 @@ jobs: GITHUB_REPO_URL: https://github.com/${{ github.repository }} steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit @@ -471,7 +471,7 @@ jobs: path: Yubico.NativeShims.*.nupkg - name: Generate artifact attestation - uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 + uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0 with: subject-path: | Yubico.NativeShims/**/*.dll @@ -489,7 +489,7 @@ jobs: if: ${{ github.event.inputs.push-to-dev == 'true' }} steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit diff --git a/.github/workflows/build-pull-requests.yml b/.github/workflows/build-pull-requests.yml index ee2d2a1b6..48df12369 100644 --- a/.github/workflows/build-pull-requests.yml +++ b/.github/workflows/build-pull-requests.yml @@ -51,11 +51,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aa7a74634..100e3870a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,11 +82,11 @@ jobs: assemblies-id: ${{ steps.assemblies-upload.outputs.artifact-id }} steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 @@ -169,7 +169,7 @@ jobs: # Generate artifact attestation - name: Generate artifact attestation - uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8 # v3.1.0 + uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0 with: subject-path: | Yubico.Core/src/bin/Release/*.nupkg @@ -200,7 +200,7 @@ jobs: contents: read steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit @@ -227,7 +227,7 @@ jobs: if: always() steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index f1822e1a7..d0930eb32 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -30,19 +30,19 @@ jobs: actions: read # Required for Claude to read CI results on PRs steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 1 persist-credentials: false - name: Run Claude Code id: claude - uses: anthropics/claude-code-action@1b8ee3b94104046d71fde52ec3557651ad8c0d71 # v1.0.29 + uses: anthropics/claude-code-action@2817c54db8f44f3a0485d57292566bf07d428a25 # v1.0.37 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 709630840..ab28ec6ee 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -55,12 +55,12 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -74,7 +74,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: # Override automatic language detection to only analyze C# # C/C++ code in Yubico.NativeShims is built separately (requires CMake/vcpkg) @@ -87,4 +87,4 @@ jobs: NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 83c9c121a..690337a46 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - name: 'Checkout Repository' - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 6212e1136..f607d7906 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -27,12 +27,12 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - name: Check out current repo - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: self persist-credentials: false @@ -54,7 +54,7 @@ jobs: private-key: ${{ secrets.GH_APP_YUBICO_DOCS_PRIVATE_KEY }} - name: Check out docs-gitops repo (${{ inputs.gitops-branch }} branch) - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: Yubico/docs-gitops ref: ${{ inputs.gitops-branch }} @@ -88,12 +88,12 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index a650c0be9..730c19d8f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -35,12 +35,12 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - name: "Checkout code" - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -79,6 +79,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: sarif_file: results.sarif diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index a367e631b..6726c769c 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -31,11 +31,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 4db006eec..8e92dc127 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -31,11 +31,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 74203e16f..88f28a916 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -31,11 +31,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cd74b1873..8c5d0096d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -81,7 +81,7 @@ jobs: if: inputs.build-coverage-report == true steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit @@ -129,7 +129,7 @@ jobs: if: github.event_name == 'pull_request' steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit @@ -157,7 +157,7 @@ jobs: if: github.event_name == 'pull_request' steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit diff --git a/.github/workflows/upload-docs.yml b/.github/workflows/upload-docs.yml index 765aaccfa..4a67844e9 100644 --- a/.github/workflows/upload-docs.yml +++ b/.github/workflows/upload-docs.yml @@ -45,11 +45,11 @@ jobs: steps: # Checkout the local repository as we need the Dockerfile and other things even for this step. - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/.github/workflows/verify-code-style.yml b/.github/workflows/verify-code-style.yml index 91f20b45e..45f1f11f4 100644 --- a/.github/workflows/verify-code-style.yml +++ b/.github/workflows/verify-code-style.yml @@ -37,11 +37,11 @@ jobs: steps: - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 with: egress-policy: audit - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 From c8f6416c4cee41148974b9f8f3c22deadba0c7ec Mon Sep 17 00:00:00 2001 From: Dennis Dyall Date: Wed, 28 Jan 2026 10:25:29 +0100 Subject: [PATCH 49/50] docs: update release notes for version 1.15.1 with bug fix details --- docs/users-manual/getting-started/whats-new.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/users-manual/getting-started/whats-new.md b/docs/users-manual/getting-started/whats-new.md index 9cc321aa2..47daa4016 100644 --- a/docs/users-manual/getting-started/whats-new.md +++ b/docs/users-manual/getting-started/whats-new.md @@ -22,6 +22,9 @@ Here you can find all of the updates and release notes for published versions of Release date: January 28th, 2026 +Bug Fixes: +- Fixed regression in Piv sample app ([#398](https://github.com/Yubico/Yubico.NET.SDK/pull/398) + Documentation: - The documentation on [PIV certificate sizes](xref:UsersManualPivCertSizes) has been restructured to improve clarity and readability. Additionally, firmware behavior details and practical examples have been added/updated. ([#356](https://github.com/Yubico/Yubico.NET.SDK/pull/356)) From f7bfcb40e8368993cbf413043bcb946ae93d4192 Mon Sep 17 00:00:00 2001 From: Dennis Dyall Date: Wed, 28 Jan 2026 10:25:34 +0100 Subject: [PATCH 50/50] bump: update CommonVersion to 1.15.1 --- build/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Versions.props b/build/Versions.props index ea0289488..00eccace8 100644 --- a/build/Versions.props +++ b/build/Versions.props @@ -33,7 +33,7 @@ for external milestones. - 1.15.0 + 1.15.1