diff --git a/dotnet/src/VectorData/Redis/RedisFilterTranslator.cs b/dotnet/src/VectorData/Redis/RedisFilterTranslator.cs index d69655d4afb2..78643ead0cc4 100644 --- a/dotnet/src/VectorData/Redis/RedisFilterTranslator.cs +++ b/dotnet/src/VectorData/Redis/RedisFilterTranslator.cs @@ -258,8 +258,8 @@ private void TranslateAny(Expression source, LambdaExpression lambda) private static string SanitizeStringConstant(string value) #if NET - => value.Replace("\"", "\\\"", StringComparison.Ordinal); + => value.Replace("\\", "\\\\", StringComparison.Ordinal).Replace("\"", "\\\"", StringComparison.Ordinal); #else - => value.Replace("\"", "\\\""); + => value.Replace("\\", "\\\\").Replace("\"", "\\\""); #endif } diff --git a/dotnet/test/VectorData/Redis.UnitTests/RedisFilterTranslatorTests.cs b/dotnet/test/VectorData/Redis.UnitTests/RedisFilterTranslatorTests.cs index 789a1c25142e..3b937aa3fe4e 100644 --- a/dotnet/test/VectorData/Redis.UnitTests/RedisFilterTranslatorTests.cs +++ b/dotnet/test/VectorData/Redis.UnitTests/RedisFilterTranslatorTests.cs @@ -108,6 +108,58 @@ public void Equal_with_double_quote_in_value() Assert.Equal("""@Name:{"foo\"bar"}""", result); } + [Fact] + public void Equal_with_backslash_in_value() + { + var result = Translate(r => r.Name == "foo\\bar"); + Assert.Equal("""@Name:{"foo\\bar"}""", result); + } + + [Fact] + public void Equal_with_single_backslash() + { + var result = Translate(r => r.Name == "\\"); + Assert.Equal("""@Name:{"\\"}""", result); + } + + [Fact] + public void Equal_with_backslash_quote_injection_attempt() + { + // Input: \" which should NOT break out of the quoted string + var result = Translate(r => r.Name == "\\\""); + Assert.Equal("""@Name:{"\\\""}""", result); + } + + [Fact] + public void Equal_with_backslash_quote_wildcard_injection() + { + // The specific attack payload: \" | * | \" + var result = Translate(r => r.Name == "\\\" | * | \\\""); + Assert.Equal("""@Name:{"\\\" | * | \\\""}""", result); + } + + [Fact] + public void Contains_with_backslash_in_value() + { + var result = Translate(r => r.Tags.Contains("foo\\bar")); + Assert.Equal("""@Tags:{"foo\\bar"}""", result); + } + + [Fact] + public void Contains_with_backslash_quote_injection_attempt() + { + var result = Translate(r => r.Tags.Contains("\\\"")); + Assert.Equal("""@Tags:{"\\\""}""", result); + } + + [Fact] + public void Any_with_backslash_in_values() + { + var values = new[] { "a\\b", "c\\d" }; + var result = Translate(r => r.Tags.Any(t => values.Contains(t))); + Assert.Equal("""@Tags:{"a\\b" | "c\\d"}""", result); + } + private static string Translate(Expression> filter) { var model = BuildModel();