From 0e0d7737dcda1a110b4aef74aeec53a5526fd96c Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Fri, 26 Sep 2025 21:38:39 +0000 Subject: [PATCH 1/3] fix: Add validation format check for SDK key --- .../common/src/Helpers/ValidationUtils.cs | 29 ++++++++- .../test/Helpers/ValidationUtilsTest.cs | 62 ++++++++++++++++--- 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/pkgs/shared/common/src/Helpers/ValidationUtils.cs b/pkgs/shared/common/src/Helpers/ValidationUtils.cs index 7a11780d..ee526689 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. + /// Null if the input is valid, otherwise an error string describing the issue. + 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] From 7ca16a9ed4f4ea5524249eb4069b714e91fb1267 Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Fri, 26 Sep 2025 21:42:09 +0000 Subject: [PATCH 2/3] fix the return comment --- pkgs/shared/common/src/Helpers/ValidationUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/shared/common/src/Helpers/ValidationUtils.cs b/pkgs/shared/common/src/Helpers/ValidationUtils.cs index ee526689..f66fc99c 100644 --- a/pkgs/shared/common/src/Helpers/ValidationUtils.cs +++ b/pkgs/shared/common/src/Helpers/ValidationUtils.cs @@ -15,7 +15,7 @@ public static class ValidationUtils /// Validates that a string does not contain invalid characters and is not too long for our systems. /// /// the SDK key to validate. - /// Null if the input is valid, otherwise an error string describing the issue. + /// True if the SDK key is valid or null/empty, false if it is invalid. public static bool IsValidSdkKeyFormat(string sdkKey) { // For offline mode, we allow a null or empty SDK key and it is not invalid. From 1d0d1e6bccaddb5cae8ef05b8ad191d4c4954b7f Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Fri, 26 Sep 2025 21:45:47 +0000 Subject: [PATCH 3/3] adjust wording in comment --- pkgs/shared/common/src/Helpers/ValidationUtils.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/shared/common/src/Helpers/ValidationUtils.cs b/pkgs/shared/common/src/Helpers/ValidationUtils.cs index f66fc99c..b66b84cb 100644 --- a/pkgs/shared/common/src/Helpers/ValidationUtils.cs +++ b/pkgs/shared/common/src/Helpers/ValidationUtils.cs @@ -15,7 +15,7 @@ public static class ValidationUtils /// 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 is valid or null/empty, false if it is invalid. + /// 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.