.Net: Add backslash escaping to redis text search values (#13902)

### Motivation and Context

### Description

- Add backslash escaping to redis text search values

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [ ] The code builds clean without any errors or warnings
- [ ] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [ ] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄
This commit is contained in:
westey
2026-04-21 14:17:31 +00:00
committed by GitHub
parent bf1b19c84c
commit ba37e8e49b
2 changed files with 54 additions and 2 deletions
@@ -258,8 +258,8 @@ internal class RedisFilterTranslator : FilterTranslatorBase
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
}
@@ -108,6 +108,58 @@ public sealed class RedisFilterTranslatorTests
Assert.Equal("""@Name:{"foo\"bar"}""", result);
}
[Fact]
public void Equal_with_backslash_in_value()
{
var result = Translate<TestRecord>(r => r.Name == "foo\\bar");
Assert.Equal("""@Name:{"foo\\bar"}""", result);
}
[Fact]
public void Equal_with_single_backslash()
{
var result = Translate<TestRecord>(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<TestRecord>(r => r.Name == "\\\"");
Assert.Equal("""@Name:{"\\\""}""", result);
}
[Fact]
public void Equal_with_backslash_quote_wildcard_injection()
{
// The specific attack payload: \" | * | \"
var result = Translate<TestRecord>(r => r.Name == "\\\" | * | \\\"");
Assert.Equal("""@Name:{"\\\" | * | \\\""}""", result);
}
[Fact]
public void Contains_with_backslash_in_value()
{
var result = Translate<TestRecord>(r => r.Tags.Contains("foo\\bar"));
Assert.Equal("""@Tags:{"foo\\bar"}""", result);
}
[Fact]
public void Contains_with_backslash_quote_injection_attempt()
{
var result = Translate<TestRecord>(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<TestRecord>(r => r.Tags.Any(t => values.Contains(t)));
Assert.Equal("""@Tags:{"a\\b" | "c\\d"}""", result);
}
private static string Translate<TRecord>(Expression<Func<TRecord, bool>> filter)
{
var model = BuildModel();