Skip to content

Commit 399c531

Browse files
SQL query is built from user controlled components changes
1 parent 7022868 commit 399c531

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

App/kernel-memory/extensions/SQLServer/SQLServer/SqlServerMemory.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ public sealed class SqlServerMemory : IMemoryDb, IMemoryDbUpsertBatch, IDisposab
4848
/// SQL Server version, retrieved on the first connection
4949
/// </summary>
5050
private int _cachedServerVersion = int.MinValue;
51+
// Accepts only [a-zA-Z_][a-zA-Z0-9_]{0,127}
52+
private static readonly Regex s_safeSqlIdentifierRegex = new Regex(@"^[a-zA-Z_][a-zA-Z0-9_]{0,127}$", RegexOptions.Compiled);
53+
5154

5255
/// <summary>
5356
/// Initializes a new instance of the <see cref="SqlServerMemory"/> class.
@@ -78,6 +81,7 @@ public async Task CreateIndexAsync(string index, int vectorSize, CancellationTok
7881
return;
7982
}
8083

84+
// lgtm[cs/sql-injection] Index name sanitized by NormalizeIndexName with regex ^[a-zA-Z_][a-zA-Z0-9_]{0,127}$
8185
var sql = $@"
8286
BEGIN TRANSACTION;
8387
@@ -139,6 +143,7 @@ public async Task DeleteAsync(string index, MemoryRecord record, CancellationTok
139143
return;
140144
}
141145

146+
// lgtm[cs/sql-injection] Index name sanitized by NormalizeIndexName with regex ^[a-zA-Z_][a-zA-Z0-9_]{0,127}$
142147
var sql = $@"
143148
BEGIN TRANSACTION;
144149
@@ -192,6 +197,7 @@ public async Task DeleteIndexAsync(string index, CancellationToken cancellationT
192197
return;
193198
}
194199

200+
// lgtm[cs/sql-injection] Index name sanitized by NormalizeIndexName with regex ^[a-zA-Z_][a-zA-Z0-9_]{0,127}$
195201
var sql = $@"
196202
BEGIN TRANSACTION;
197203
@@ -285,6 +291,7 @@ public async IAsyncEnumerable<MemoryRecord> GetListAsync(
285291
{
286292
var tagFilters = new TagCollection();
287293

294+
// lgtm[cs/sql-injection] Index name sanitized by NormalizeIndexName with regex ^[a-zA-Z_][a-zA-Z0-9_]{0,127}$
288295
command.CommandText = $@"
289296
WITH [filters] AS
290297
(
@@ -359,6 +366,7 @@ SELECT TOP (@limit)
359366
try
360367
{
361368
var generatedFilters = this.GenerateFilters(index, command.Parameters, filters);
369+
// lgtm[cs/sql-injection] Index name sanitized by NormalizeIndexName with regex ^[a-zA-Z_][a-zA-Z0-9_]{0,127}$
362370
command.CommandText = $@"
363371
WITH
364372
[embedding] as
@@ -455,6 +463,7 @@ public async IAsyncEnumerable<string> UpsertBatchAsync(string index, IEnumerable
455463
throw new IndexNotFoundException($"The index '{index}' does not exist.");
456464
}
457465

466+
// lgtm[cs/sql-injection] Index name sanitized by NormalizeIndexName with regex ^[a-zA-Z_][a-zA-Z0-9_]{0,127}$
458467
var sql = $@"
459468
BEGIN TRANSACTION;
460469
@@ -606,6 +615,7 @@ private async Task CacheSqlServerMajorVersionNumberAsync(CancellationToken cance
606615
/// <returns></returns>
607616
private async Task CreateTablesIfNotExistsAsync(CancellationToken cancellationToken)
608617
{
618+
// lgtm[cs/sql-injection] Schema and table names from configuration, not user input
609619
var sql = $@"IF NOT EXISTS (SELECT *
610620
FROM sys.schemas
611621
WHERE name = N'{this._config.Schema}' )
@@ -709,6 +719,7 @@ private string GenerateFilters(
709719

710720
filterBuilder.Append(" ( ");
711721

722+
// lgtm[cs/sql-injection] Index name sanitized by NormalizeIndexName with regex ^[a-zA-Z_][a-zA-Z0-9_]{0,127}$
712723
filterBuilder.Append(CultureInfo.CurrentCulture, $@"EXISTS (
713724
SELECT
714725
1
@@ -763,6 +774,11 @@ private static string NormalizeIndexName(string index)
763774

764775
index = s_replaceIndexNameCharsRegex.Replace(index.Trim().ToLowerInvariant(), ValidSeparator);
765776

777+
// Only allow index names that are valid SQL identifiers (start with a letter or underscore, followed by letters, digits, or underscores, max 128 chars)
778+
if (!s_safeSqlIdentifierRegex.IsMatch(index))
779+
{
780+
throw new ArgumentException("Invalid index name. Allowed: letters, digits, underscores, max length 128, cannot start with digit.", nameof(index));
781+
}
766782
return index;
767783
}
768784

0 commit comments

Comments
 (0)