diff --git a/pkgs/shared/common/src/Helpers/ValidationUtils.cs b/pkgs/shared/common/src/Helpers/ValidationUtils.cs
index 7a11780d..b66b84cb 100644
--- a/pkgs/shared/common/src/Helpers/ValidationUtils.cs
+++ b/pkgs/shared/common/src/Helpers/ValidationUtils.cs
@@ -9,9 +9,36 @@ namespace LaunchDarkly.Sdk.Helpers
public static class ValidationUtils
{
private static readonly Regex ValidCharsRegex = new Regex("^[-a-zA-Z0-9._]+\\z");
+ private const int MaxSdkKeyLength = 8192;
///
- /// Validates that a string is non-empty, not too longer for our systems, and only contains
+ /// Validates that a string does not contain invalid characters and is not too long for our systems.
+ ///
+ /// the SDK key to validate.
+ /// True if the SDK key format is valid, otherwise false.
+ public static bool IsValidSdkKeyFormat(string sdkKey)
+ {
+ // For offline mode, we allow a null or empty SDK key and it is not invalid.
+ if (string.IsNullOrEmpty(sdkKey))
+ {
+ return true;
+ }
+
+ if (sdkKey.Length > MaxSdkKeyLength)
+ {
+ return false;
+ }
+
+ if (!ValidCharsRegex.IsMatch(sdkKey))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ /// Validates that a string is non-empty, not too long for our systems, and only contains
/// alphanumeric characters, hyphens, periods, and underscores.
///
/// the string to validate.
diff --git a/pkgs/shared/common/test/Helpers/ValidationUtilsTest.cs b/pkgs/shared/common/test/Helpers/ValidationUtilsTest.cs
index 26f9c342..12d56aa9 100644
--- a/pkgs/shared/common/test/Helpers/ValidationUtilsTest.cs
+++ b/pkgs/shared/common/test/Helpers/ValidationUtilsTest.cs
@@ -4,18 +4,60 @@ namespace LaunchDarkly.Sdk.Helpers
{
public class ValidationUtilsTest
{
+ [Theory]
+ [InlineData(null)]
+ [InlineData("")]
+ public void IsValidSdkKeyFormat_EmptyOrNullKey_ReturnsTrue(string key)
+ {
+ Assert.True(ValidationUtils.IsValidSdkKeyFormat(key));
+ }
+
+ [Theory]
+ [InlineData("sdk-key-123")]
+ [InlineData("sdk.key.123")]
+ [InlineData("sdk_key_123")]
+ [InlineData("SDKKEY123")]
+ public void IsValidSdkKeyFormat_ValidKey_ReturnsTrue(string key)
+ {
+ Assert.True(ValidationUtils.IsValidSdkKeyFormat(key));
+ }
+
[Fact]
- public void ValidateStringValue()
+ public void IsValidSdkKeyFormat_TooLongKey_ReturnsFalseWithError()
+ {
+ var longKey = new string('a', 8193); // Creates a string longer than MaxSdkKeyLength (8192)
+ Assert.False(ValidationUtils.IsValidSdkKeyFormat(longKey));
+ }
+
+ [Theory]
+ [InlineData("sdk key")] // Contains space
+ [InlineData("sdk#key")] // Contains special character
+ [InlineData("sdk/key")] // Contains slash
+ [InlineData("sdk\nkey")] // Contains newline
+ public void IsValidSdkKeyFormat_InvalidCharacters_ReturnsFalseWithError(string key)
+ {
+ Assert.False(ValidationUtils.IsValidSdkKeyFormat(key));
+ }
+
+ [Theory]
+ [InlineData("bad-\n")] // Contains newline
+ [InlineData("bad-\t")] // Contains tab
+ [InlineData("###invalid")] // Contains special characters
+ [InlineData("")] // Empty string
+ [InlineData("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEFwhoops")] // Too long
+ [InlineData("#@$%^&")] // Invalid characters
+ public void ValidateStringValue_Invalid_ReturnsErrorMessage(string input)
+ {
+ Assert.NotNull(ValidationUtils.ValidateStringValue(input));
+ }
+
+ [Theory]
+ [InlineData("a-Az-Z0-9._-")]
+ [InlineData("valid-string-123")]
+ [InlineData("VALIDSTRING")]
+ public void ValidateStringValue_Valid_ReturnsNull(string input)
{
- Assert.NotNull(ValidationUtils.ValidateStringValue("bad-\n"));
- Assert.NotNull(ValidationUtils.ValidateStringValue("bad-\t"));
- Assert.NotNull(ValidationUtils.ValidateStringValue("###invalid"));
- Assert.NotNull(ValidationUtils.ValidateStringValue(""));
- Assert.NotNull(
- ValidationUtils.ValidateStringValue(
- "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEFwhoops"));
- Assert.NotNull(ValidationUtils.ValidateStringValue("#@$%^&"));
- Assert.Null(ValidationUtils.ValidateStringValue("a-Az-Z0-9._-"));
+ Assert.Null(ValidationUtils.ValidateStringValue(input));
}
[Fact]