diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index e2e795ecd269..31a6cdbc7511 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -24,8 +24,8 @@
-
-
+
+
@@ -65,7 +65,7 @@
-
+
@@ -92,17 +92,20 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
@@ -110,9 +113,9 @@
-
-
-
+
+
+
@@ -120,10 +123,10 @@
-
-
+
+
-
+
@@ -139,7 +142,7 @@
-
+
@@ -152,7 +155,7 @@
-
+
diff --git a/dotnet/SK-release.slnf b/dotnet/SK-release.slnf
index 1b497da3f66e..e3abf0b9db6e 100644
--- a/dotnet/SK-release.slnf
+++ b/dotnet/SK-release.slnf
@@ -3,74 +3,8 @@
"path": "SK-dotnet.slnx",
"projects":
[
- "src\\SemanticKernel.Abstractions\\SemanticKernel.Abstractions.csproj",
- "src\\SemanticKernel.Core\\SemanticKernel.Core.csproj",
- "src\\SemanticKernel.MetaPackage\\SemanticKernel.MetaPackage.csproj",
-
- "src\\Agents\\A2A\\Agents.A2A.csproj",
- "src\\Agents\\Abstractions\\Agents.Abstractions.csproj",
- "src\\Agents\\AzureAI\\Agents.AzureAI.csproj",
- "src\\Agents\\Bedrock\\Agents.Bedrock.csproj",
- "src\\Agents\\Copilot\\Agents.CopilotStudio.csproj",
- "src\\Agents\\Core\\Agents.Core.csproj",
- "src\\Agents\\Magentic\\Agents.Magentic.csproj",
- "src\\Agents\\OpenAI\\Agents.OpenAI.csproj",
- "src\\Agents\\Orchestration\\Agents.Orchestration.csproj",
- "src\\Agents\\Yaml\\Agents.Yaml.csproj",
-
- "src\\Agents\\Runtime\\Abstractions\\Runtime.Abstractions.csproj",
- "src\\Agents\\Runtime\\Core\\Runtime.Core.csproj",
- "src\\Agents\\Runtime\\InProcess\\Runtime.InProcess.csproj",
-
- "src\\Connectors\\Connectors.Amazon\\Connectors.Amazon.csproj",
- "src\\Connectors\\Connectors.AzureAIInference\\Connectors.AzureAIInference.csproj",
- "src\\Connectors\\Connectors.AzureOpenAI\\Connectors.AzureOpenAI.csproj",
- "src\\Connectors\\Connectors.Google\\Connectors.Google.csproj",
- "src\\Connectors\\Connectors.HuggingFace\\Connectors.HuggingFace.csproj",
- "src\\Connectors\\Connectors.MistralAI\\Connectors.MistralAI.csproj",
- "src\\Connectors\\Connectors.Ollama\\Connectors.Ollama.csproj",
- "src\\Connectors\\Connectors.Onnx\\Connectors.Onnx.csproj",
- "src\\Connectors\\Connectors.OpenAI\\Connectors.OpenAI.csproj",
-
- "src\\VectorData\\AzureAISearch\\AzureAISearch.csproj",
- "src\\VectorData\\Chroma\\Chroma.csproj",
- "src\\VectorData\\CosmosMongoDB\\CosmosMongoDB.csproj",
- "src\\VectorData\\CosmosNoSql\\CosmosNoSql.csproj",
- "src\\VectorData\\InMemory\\InMemory.csproj",
- "src\\VectorData\\Milvus\\Milvus.csproj",
- "src\\VectorData\\MongoDB\\MongoDB.csproj",
- "src\\VectorData\\PgVector\\PgVector.csproj",
- "src\\VectorData\\Pinecone\\Pinecone.csproj",
- "src\\VectorData\\Qdrant\\Qdrant.csproj",
"src\\VectorData\\Redis\\Redis.csproj",
- "src\\VectorData\\SqliteVec\\SqliteVec.csproj",
"src\\VectorData\\SqlServer\\SqlServer.csproj",
- "src\\VectorData\\VectorData.Abstractions\\VectorData.Abstractions.csproj",
- "src\\VectorData\\Weaviate\\Weaviate.csproj",
-
- "src\\Experimental\\Orchestration.Flow\\Experimental.Orchestration.Flow.csproj",
-
- "src\\Experimental\\Process.Abstractions\\Process.Abstractions.csproj",
- "src\\Experimental\\Process.Core\\Process.Core.csproj",
- "src\\Experimental\\Process.LocalRuntime\\Process.LocalRuntime.csproj",
- "src\\Experimental\\Process.Runtime.Dapr\\Process.Runtime.Dapr.csproj",
-
- "src\\Functions\\Functions.Grpc\\Functions.Grpc.csproj",
- "src\\Functions\\Functions.OpenApi.Extensions\\Functions.OpenApi.Extensions.csproj",
- "src\\Functions\\Functions.OpenApi\\Functions.OpenApi.csproj",
- "src\\Functions\\Functions.Prompty\\Functions.Prompty.csproj",
- "src\\Functions\\Functions.Yaml\\Functions.Yaml.csproj",
-
- "src\\Extensions\\PromptTemplates.Handlebars\\PromptTemplates.Handlebars.csproj",
- "src\\Extensions\\PromptTemplates.Liquid\\PromptTemplates.Liquid.csproj",
-
- "src\\Plugins\\Plugins.AI\\Plugins.AI.csproj",
- "src\\Plugins\\Plugins.Core\\Plugins.Core.csproj",
- "src\\Plugins\\Plugins.Document\\Plugins.Document.csproj",
- "src\\Plugins\\Plugins.Memory\\Plugins.Memory.csproj",
- "src\\Plugins\\Plugins.MsGraph\\Plugins.MsGraph.csproj",
- "src\\Plugins\\Plugins.StructuredData.EntityFramework\\Plugins.StructuredData.EntityFramework.csproj",
- "src\\Plugins\\Plugins.Web\\Plugins.Web.csproj"
]
}
}
diff --git a/dotnet/nuget/nuget-package.props b/dotnet/nuget/nuget-package.props
index 016deb5eaf36..cf4203674e08 100644
--- a/dotnet/nuget/nuget-package.props
+++ b/dotnet/nuget/nuget-package.props
@@ -1,7 +1,7 @@
- 1.74.0
+ 1.74.1
$(VersionPrefix)-$(VersionSuffix)
$(VersionPrefix)
diff --git a/dotnet/samples/Demos/TelemetryWithAppInsights/TelemetryWithAppInsights.csproj b/dotnet/samples/Demos/TelemetryWithAppInsights/TelemetryWithAppInsights.csproj
index 2b245bf45b41..e75746d4b69e 100644
--- a/dotnet/samples/Demos/TelemetryWithAppInsights/TelemetryWithAppInsights.csproj
+++ b/dotnet/samples/Demos/TelemetryWithAppInsights/TelemetryWithAppInsights.csproj
@@ -13,6 +13,10 @@
+
+
+
+
diff --git a/dotnet/src/SemanticKernel.Core/Functions/KernelFunctionFromMethod.cs b/dotnet/src/SemanticKernel.Core/Functions/KernelFunctionFromMethod.cs
index cc6d3eabf498..4dab37f0f8a4 100644
--- a/dotnet/src/SemanticKernel.Core/Functions/KernelFunctionFromMethod.cs
+++ b/dotnet/src/SemanticKernel.Core/Functions/KernelFunctionFromMethod.cs
@@ -720,7 +720,7 @@ private static (Func value.Replace("\"", "\\\"", StringComparison.Ordinal);
+ => value.Replace("\\", "\\\\", StringComparison.Ordinal).Replace("\"", "\\\"", StringComparison.Ordinal);
#else
- => value.Replace("\"", "\\\"");
+ => value.Replace("\\", "\\\\").Replace("\"", "\\\"");
#endif
}
diff --git a/dotnet/src/VectorData/SqlServer/SqlServerCommandBuilder.cs b/dotnet/src/VectorData/SqlServer/SqlServerCommandBuilder.cs
index eabfc794f34e..1da2a7422805 100644
--- a/dotnet/src/VectorData/SqlServer/SqlServerCommandBuilder.cs
+++ b/dotnet/src/VectorData/SqlServer/SqlServerCommandBuilder.cs
@@ -31,7 +31,7 @@ internal static List CreateTable(
if (ifNotExists)
{
sb.Append("IF OBJECT_ID(N'");
- sb.AppendTableName(schema, tableName);
+ sb.AppendTableNameInsideLiteral(schema, tableName);
sb.AppendLine("', N'U') IS NULL");
}
sb.AppendLine("BEGIN");
@@ -125,22 +125,22 @@ internal static List CreateTable(
// Full-text indexes require a unique index (we use the primary key)
sb.AppendLine("DECLARE @pkIndexName NVARCHAR(128);");
sb.Append("SELECT @pkIndexName = name FROM sys.indexes WHERE object_id = OBJECT_ID(N'");
- sb.AppendTableName(schema, tableName);
+ sb.AppendTableNameInsideLiteral(schema, tableName);
sb.AppendLine("') AND is_primary_key = 1;");
sb.AppendLine("DECLARE @ftSql NVARCHAR(MAX);");
sb.Append("SET @ftSql = N'CREATE FULLTEXT INDEX ON ");
- sb.AppendTableName(schema, tableName).Append(" (");
+ sb.AppendTableNameInsideLiteral(schema, tableName).Append(" (");
for (int i = 0; i < fullTextProperties.Count; i++)
{
- sb.AppendIdentifier(fullTextProperties[i].StorageName);
+ sb.AppendIdentifierInsideLiteral(fullTextProperties[i].StorageName);
if (i < fullTextProperties.Count - 1)
{
sb.Append(',');
}
}
sb.Append(") KEY INDEX ' + QUOTENAME(@pkIndexName) + N' ON ");
- sb.AppendIdentifier(catalogName).AppendLine("';");
+ sb.AppendIdentifierInsideLiteral(catalogName).AppendLine("';");
sb.AppendLine("EXEC sp_executesql @ftSql;");
}
@@ -864,6 +864,30 @@ internal static StringBuilder AppendIdentifier(this StringBuilder sb, string ide
return sb;
}
+ ///
+ /// Same as , but for use inside a SQL string literal (N'...'),
+ /// where single quotes must be escaped by doubling them.
+ ///
+ internal static StringBuilder AppendTableNameInsideLiteral(this StringBuilder sb, string? schema, string tableName)
+ {
+ int start = sb.Length;
+ sb.AppendTableName(schema, tableName);
+ sb.Replace("'", "''", start, sb.Length - start);
+ return sb;
+ }
+
+ ///
+ /// Same as , but for use inside a SQL string literal (N'...'),
+ /// where single quotes must be escaped by doubling them.
+ ///
+ internal static StringBuilder AppendIdentifierInsideLiteral(this StringBuilder sb, string identifier)
+ {
+ int start = sb.Length;
+ sb.AppendIdentifier(identifier);
+ sb.Replace("'", "''", start, sb.Length - start);
+ return sb;
+ }
+
private static StringBuilder AppendIdentifiers(this StringBuilder sb,
IEnumerable properties,
string? prefix = null,
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();
diff --git a/dotnet/test/VectorData/SqlServer.ConformanceTests/SqlServerCommandBuilderTests.cs b/dotnet/test/VectorData/SqlServer.ConformanceTests/SqlServerCommandBuilderTests.cs
index b78a010d6b4c..5d56967ed1ca 100644
--- a/dotnet/test/VectorData/SqlServer.ConformanceTests/SqlServerCommandBuilderTests.cs
+++ b/dotnet/test/VectorData/SqlServer.ConformanceTests/SqlServerCommandBuilderTests.cs
@@ -27,6 +27,36 @@ public void AppendTableName(string? schema, string table, string expectedFullNam
Assert.Equal(expectedFullName, result.ToString());
}
+ [Theory]
+ [InlineData("schema", "name", "[schema].[name]")]
+ [InlineData(null, "name", "[name]")]
+ [InlineData("schema", "it's", "[schema].[it''s]")]
+ [InlineData("it's", "name", "[it''s].[name]")]
+ [InlineData("it's", "it's", "[it''s].[it''s]")]
+ [InlineData(null, "it's", "[it''s]")]
+ [InlineData("schema", "[brackets]", "[schema].[[brackets]]]")]
+ public void AppendTableNameInsideLiteral(string? schema, string table, string expectedFullName)
+ {
+ StringBuilder result = new();
+
+ SqlServerCommandBuilder.AppendTableNameInsideLiteral(result, schema, table);
+
+ Assert.Equal(expectedFullName, result.ToString());
+ }
+
+ [Theory]
+ [InlineData("name", "[name]")]
+ [InlineData("it's", "[it''s]")]
+ [InlineData("two''quotes", "[two''''quotes]")]
+ public void AppendIdentifierInsideLiteral(string identifier, string expected)
+ {
+ StringBuilder result = new();
+
+ SqlServerCommandBuilder.AppendIdentifierInsideLiteral(result, identifier);
+
+ Assert.Equal(expected, result.ToString());
+ }
+
[Theory]
[InlineData("name", "@name_")] // typical name
[InlineData("na me", "@na_")] // contains a whitespace, an illegal parameter name character
@@ -149,6 +179,34 @@ PRIMARY KEY ([id])
Assert.Equal(expectedCommand, command.CommandText, ignoreLineEndingDifferences: true);
}
+ [Fact]
+ public void CreateTable_WithSingleQuoteInName()
+ {
+ var model = BuildModel(
+ [
+ new VectorStoreKeyProperty("id", typeof(long)),
+ new VectorStoreDataProperty("name", typeof(string)),
+ ]);
+
+ using SqlConnection connection = CreateConnection();
+
+ var commands = SqlServerCommandBuilder.CreateTable(connection, "it's", "ta'ble", ifNotExists: true, model);
+
+ var command = Assert.Single(commands);
+ Assert.Equal(
+ "IF OBJECT_ID(N'[it''s].[ta''ble]', N'U') IS NULL" + Environment.NewLine +
+ """
+ BEGIN
+ CREATE TABLE [it's].[ta'ble] (
+ [id] BIGINT IDENTITY,
+ [name] NVARCHAR(MAX),
+ PRIMARY KEY ([id])
+ );
+ END;
+ """,
+ command.CommandText, ignoreLineEndingDifferences: true);
+ }
+
[Fact]
public void CreateTable_WithDiskAnnIndex()
{