diff --git a/java/src/org/openqa/selenium/virtualauthenticator/Credential.java b/java/src/org/openqa/selenium/virtualauthenticator/Credential.java
index de239698eed64..fa293239d1356 100644
--- a/java/src/org/openqa/selenium/virtualauthenticator/Credential.java
+++ b/java/src/org/openqa/selenium/virtualauthenticator/Credential.java
@@ -23,6 +23,8 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
import org.openqa.selenium.internal.Require;
/**
@@ -31,13 +33,14 @@
* @see https://w3c.github.io/webauthn/#credential-parameters
*/
+@NullMarked
public class Credential {
private final byte[] id;
private final boolean isResidentCredential;
private final String rpId;
private final PKCS8EncodedKeySpec privateKey;
- private final byte[] userHandle;
+ private final byte @Nullable [] userHandle;
private final int signCount;
/** Creates a non resident (i.e. stateless) credential. */
@@ -75,7 +78,7 @@ private Credential(
boolean isResidentCredential,
String rpId,
PKCS8EncodedKeySpec privateKey,
- byte[] userHandle,
+ byte @Nullable [] userHandle,
int signCount) {
this.id = Require.nonNull("Id", id);
this.isResidentCredential = isResidentCredential;
@@ -101,7 +104,7 @@ public PKCS8EncodedKeySpec getPrivateKey() {
return privateKey;
}
- public byte[] getUserHandle() {
+ public byte @Nullable [] getUserHandle() {
return userHandle == null ? null : Arrays.copyOf(userHandle, userHandle.length);
}
diff --git a/java/src/org/openqa/selenium/virtualauthenticator/HasVirtualAuthenticator.java b/java/src/org/openqa/selenium/virtualauthenticator/HasVirtualAuthenticator.java
index 49899410d5e69..5b2f96f55bbbd 100644
--- a/java/src/org/openqa/selenium/virtualauthenticator/HasVirtualAuthenticator.java
+++ b/java/src/org/openqa/selenium/virtualauthenticator/HasVirtualAuthenticator.java
@@ -17,7 +17,10 @@
package org.openqa.selenium.virtualauthenticator;
+import org.jspecify.annotations.NullMarked;
+
/** Interface implemented by each driver that allows access to the virtual authenticator API. */
+@NullMarked
public interface HasVirtualAuthenticator {
/**
* Adds a virtual authenticator with the given options.
diff --git a/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticator.java b/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticator.java
index 154c57f5a4654..587bbacc45914 100644
--- a/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticator.java
+++ b/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticator.java
@@ -18,8 +18,10 @@
package org.openqa.selenium.virtualauthenticator;
import java.util.List;
+import org.jspecify.annotations.NullMarked;
/** Represents a virtual authenticator. */
+@NullMarked
public interface VirtualAuthenticator {
/**
diff --git a/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticatorOptions.java b/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticatorOptions.java
index cb360cab3edf1..792f487826105 100644
--- a/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticatorOptions.java
+++ b/java/src/org/openqa/selenium/virtualauthenticator/VirtualAuthenticatorOptions.java
@@ -20,6 +20,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import org.jspecify.annotations.NullMarked;
/**
* Options for the creation of virtual authenticators.
@@ -27,6 +28,7 @@
* @see https://w3c.github.io/webauthn/#sctn-automation
*/
+@NullMarked
public class VirtualAuthenticatorOptions {
public enum Protocol {