Skip to content

Commit ca3c7d9

Browse files
authored
.Net: Address vulnerable packages (+Update MsGraph for latest Major V5) (#12962)
### Motivation and Context This PR addresses a recent vulnerability warning received while working in the Semantic Kernel solution, limited to specific packages for Prompty, Milvus and Microsoft Graph Plugin. As part of addressing the vulnerabilities was also necessary to upgrade the logic to use the newest packages from Microsoft.Graph library.
1 parent 5caf833 commit ca3c7d9

30 files changed

+572
-205
lines changed

dotnet/Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
<PackageVersion Include="Prompty.Core" Version="0.2.3-beta" />
8585
<PackageVersion Include="PuppeteerSharp" Version="20.0.5" />
8686
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" />
87-
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.5.1" />
87+
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.6.1" />
8888
<PackageVersion Include="System.IO.Packaging" Version="8.0.1" />
8989
<PackageVersion Include="System.Linq.AsyncEnumerable" Version="10.0.0-preview.5.25277.114" />
9090
<PackageVersion Include="System.Memory.Data" Version="8.0.1" />
@@ -144,7 +144,7 @@
144144
<PackageVersion Include="DuckDB.NET.Data.Full" Version="1.2.0" />
145145
<PackageVersion Include="DuckDB.NET.Data" Version="1.1.3" />
146146
<PackageVersion Include="MongoDB.Driver" Version="2.30.0" />
147-
<PackageVersion Include="Microsoft.Graph" Version="4.51.0" />
147+
<PackageVersion Include="Microsoft.Graph" Version="5.90.0" />
148148
<PackageVersion Include="Microsoft.OpenApi" Version="1.6.24" />
149149
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="1.6.24" />
150150
<PackageVersion Include="Microsoft.OpenApi.ApiManifest" Version="0.5.6-preview" />
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using System.Text.Json;
4+
using Azure.Identity;
5+
using Microsoft.Graph;
6+
using Microsoft.SemanticKernel;
7+
using Microsoft.SemanticKernel.Plugins.MsGraph;
8+
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;
9+
10+
namespace Plugins;
11+
12+
/// <summary>
13+
/// This example shows how to use Microsoft Graph Plugin
14+
/// These examples require a valid Microsoft account and delegated/application access for the Microsoft Graph used resources.
15+
/// </summary>
16+
public class MsGraph_CalendarPlugin(ITestOutputHelper output) : BaseTest(output)
17+
{
18+
private static readonly JsonSerializerOptions s_options = new() { WriteIndented = true };
19+
20+
/// <summary>Shows how to use Microsoft Graph Calendar Plugin with AI Models.</summary>
21+
[Fact]
22+
public async Task UsingWithAIModel()
23+
{
24+
// Setup the Kernel
25+
Kernel kernel = Kernel.CreateBuilder()
26+
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
27+
.Build();
28+
29+
using var graphClient = GetGraphClient();
30+
31+
var calendarConnector = new OutlookCalendarConnector(graphClient);
32+
33+
// Add the plugin to the Kernel
34+
var graphPlugin = kernel.Plugins.AddFromObject(new CalendarPlugin(calendarConnector, jsonSerializerOptions: s_options));
35+
36+
var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
37+
38+
string Prompt = $"""
39+
1. Show me the next 10 calendar events I have
40+
2. If I don't have any event named "Semantic Kernel", please create a new event named "Semantic Kernel"
41+
starting at {DateTimeOffset.Now.AddHours(1)} with 1 hour of duration.
42+
""";
43+
44+
// Invoke the OneDrive plugin multiple times
45+
var result = await kernel.InvokePromptAsync(Prompt, new(settings));
46+
47+
Console.WriteLine(result);
48+
}
49+
50+
private static GraphServiceClient GetGraphClient()
51+
{
52+
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
53+
{
54+
ClientId = TestConfiguration.MSGraph.ClientId,
55+
TenantId = TestConfiguration.MSGraph.TenantId,
56+
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
57+
});
58+
59+
return new GraphServiceClient(credential);
60+
}
61+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using Azure.Identity;
4+
using Microsoft.Graph;
5+
using Microsoft.SemanticKernel;
6+
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;
7+
8+
namespace Plugins;
9+
10+
/// <summary>
11+
/// This example shows how to use Microsoft Graph Plugin
12+
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
13+
/// </summary>
14+
public class MsGraph_EmailPlugin(ITestOutputHelper output) : BaseTest(output)
15+
{
16+
/// <summary>Shows how to use Microsoft Graph Email Plugin with AI Models.</summary>
17+
[Fact]
18+
public async Task EmailPlugin_SendEmailToMyself()
19+
{
20+
// Setup the Kernel
21+
Kernel kernel = Kernel.CreateBuilder()
22+
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
23+
.Build();
24+
25+
using var graphClient = GetGraphClient();
26+
27+
var emailConnector = new OutlookMailConnector(graphClient);
28+
29+
// Add the plugin to the Kernel
30+
var graphPlugin = kernel.Plugins.AddFromObject(new Microsoft.SemanticKernel.Plugins.MsGraph.EmailPlugin(emailConnector));
31+
32+
var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
33+
34+
const string Prompt = """
35+
Using the tools available, please do the following:
36+
1. Get my email address
37+
2. Send an email to myself with the subject "FYI" and content "This is a very important email"
38+
3. List 10 of my email messages
39+
""";
40+
41+
// Invoke the Graph plugin with a prompt
42+
var result = await kernel.InvokePromptAsync(Prompt, new(settings));
43+
44+
Console.WriteLine(result);
45+
}
46+
47+
private static GraphServiceClient GetGraphClient()
48+
{
49+
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
50+
{
51+
ClientId = TestConfiguration.MSGraph.ClientId,
52+
TenantId = TestConfiguration.MSGraph.TenantId,
53+
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
54+
});
55+
56+
return new GraphServiceClient(credential);
57+
}
58+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using Azure.Identity;
4+
using Microsoft.Graph;
5+
using Microsoft.SemanticKernel;
6+
using Microsoft.SemanticKernel.Plugins.MsGraph;
7+
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;
8+
9+
namespace Plugins;
10+
11+
/// <summary>
12+
/// This example shows how to use Microsoft Graph Plugin
13+
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
14+
/// </summary>
15+
public class MsGraph_OneDrivePlugin(ITestOutputHelper output) : BaseTest(output)
16+
{
17+
/// <summary>Shows how to use Microsoft Graph OneDrive Plugin with AI Models.</summary>
18+
[Fact]
19+
public async Task UsingWithAIModel()
20+
{
21+
// Setup the Kernel
22+
Kernel kernel = Kernel.CreateBuilder()
23+
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
24+
.Build();
25+
26+
using var graphClient = GetGraphClient();
27+
var connector = new OneDriveConnector(graphClient);
28+
29+
// Add the plugin to the Kernel
30+
var graphPlugin = kernel.Plugins.AddFromObject(new CloudDrivePlugin(connector));
31+
32+
var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
33+
34+
const string Prompt = """
35+
I need you to do the following things with the tools available:
36+
1. Update the current file: "Resources/travelinfo.txt" to my OneDrive into the "Test" folder.
37+
2. Generate a OneDrive Link for sharing the file
38+
3. Summarize for me the contents of the uploaded file
39+
4. Show me the generated shared link.
40+
""";
41+
42+
// Invoke the OneDrive plugin multiple times
43+
var result = await kernel.InvokePromptAsync(Prompt, new(settings));
44+
45+
Console.WriteLine($"Assistant: {result}");
46+
}
47+
48+
private static GraphServiceClient GetGraphClient()
49+
{
50+
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
51+
{
52+
ClientId = TestConfiguration.MSGraph.ClientId,
53+
TenantId = TestConfiguration.MSGraph.TenantId,
54+
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
55+
});
56+
57+
return new GraphServiceClient(credential);
58+
}
59+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using System.Text.Json;
4+
using Azure.Identity;
5+
using Microsoft.Graph;
6+
using Microsoft.SemanticKernel;
7+
using Microsoft.SemanticKernel.Plugins.MsGraph;
8+
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;
9+
10+
namespace Plugins;
11+
12+
/// <summary>
13+
/// This example shows how to use Microsoft Graph Plugin
14+
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
15+
/// </summary>
16+
public class MsGraph_OrganizationHierarchyPlugin(ITestOutputHelper output) : BaseTest(output)
17+
{
18+
private static readonly JsonSerializerOptions s_options = new() { WriteIndented = true };
19+
20+
/// <summary>Shows how to use Microsoft Graph Organization Hierarchy Plugin with AI Models.</summary>
21+
[Fact]
22+
public async Task UsingWithAIModel()
23+
{
24+
// Setup the Kernel
25+
Kernel kernel = Kernel.CreateBuilder()
26+
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
27+
.Build();
28+
29+
using var graphClient = GetGraphClient();
30+
var connector = new OrganizationHierarchyConnector(graphClient);
31+
32+
// Add the plugin to the Kernel
33+
var graphPlugin = kernel.Plugins.AddFromObject(new OrganizationHierarchyPlugin(connector, s_options));
34+
35+
var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
36+
37+
const string Prompt = "I need you to show my manager details as well as my direct reports using the tools available:";
38+
39+
// Invoke the OneDrive plugin multiple times
40+
var result = await kernel.InvokePromptAsync(Prompt, new(settings));
41+
42+
Console.WriteLine($"Assistant: {result}");
43+
}
44+
45+
private static GraphServiceClient GetGraphClient()
46+
{
47+
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
48+
{
49+
ClientId = TestConfiguration.MSGraph.ClientId,
50+
TenantId = TestConfiguration.MSGraph.TenantId,
51+
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
52+
});
53+
54+
return new GraphServiceClient(credential);
55+
}
56+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using System.Text.Json;
4+
using Azure.Identity;
5+
using Microsoft.Graph;
6+
using Microsoft.SemanticKernel;
7+
using Microsoft.SemanticKernel.Plugins.MsGraph;
8+
using Microsoft.SemanticKernel.Plugins.MsGraph.Connectors;
9+
10+
namespace Plugins;
11+
12+
/// <summary>
13+
/// This example shows how to use Microsoft Graph Plugin
14+
/// These examples require a valid Microsoft account and delegated/application access for the used resources.
15+
/// </summary>
16+
public class MsGraph_TaskListPlugin(ITestOutputHelper output) : BaseTest(output)
17+
{
18+
private static readonly JsonSerializerOptions s_options = new() { WriteIndented = true };
19+
20+
/// <summary>Shows how to use Microsoft Graph To-Do Tasks Plugin with AI Models.</summary>
21+
[Fact]
22+
public async Task UsingWithAIModel()
23+
{
24+
// Setup the Kernel
25+
Kernel kernel = Kernel.CreateBuilder()
26+
.AddOpenAIChatClient(TestConfiguration.OpenAI.ChatModelId, TestConfiguration.OpenAI.ApiKey)
27+
.Build();
28+
29+
using var graphClient = GetGraphClient();
30+
var connector = new MicrosoftToDoConnector(graphClient);
31+
32+
// Add the plugin to the Kernel
33+
var graphPlugin = kernel.Plugins.AddFromObject(new TaskListPlugin(connector, jsonSerializerOptions: s_options));
34+
35+
var settings = new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() };
36+
37+
const string Prompt = """
38+
1. Show me all the tasks I have
39+
3. If I don't have a task named "Semantic Kernel", please create one
40+
""";
41+
42+
// Invoke the OneDrive plugin multiple times
43+
var result = await kernel.InvokePromptAsync(Prompt, new(settings));
44+
45+
Console.WriteLine($"Assistant: {result}");
46+
}
47+
48+
private static GraphServiceClient GetGraphClient()
49+
{
50+
var credential = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions()
51+
{
52+
ClientId = TestConfiguration.MSGraph.ClientId,
53+
TenantId = TestConfiguration.MSGraph.TenantId,
54+
RedirectUri = TestConfiguration.MSGraph.RedirectUri,
55+
});
56+
57+
return new GraphServiceClient(credential);
58+
}
59+
}

dotnet/samples/Concepts/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ dotnet test -l "console;verbosity=detailed" --filter "FullyQualifiedName=ChatCom
185185
- [DescribeAllPluginsAndFunctions](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/DescribeAllPluginsAndFunctions.cs)
186186
- [GroundednessChecks](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/GroundednessChecks.cs)
187187
- [ImportPluginFromGrpc](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/ImportPluginFromGrpc.cs)
188+
- [MsGraph_CalendarPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_CalendarPlugin.cs)
189+
- [MsGraph_EmailPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_EmailPlugin.cs)
190+
- [MsGraph_ContactsPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_ContactsPlugin.cs)
191+
- [MsGraph_DrivePlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_DrivePlugin.cs)
192+
- [MsGraph_TasksPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/MsGraph_TasksPlugin.cs)
188193
- [TransformPlugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/TransformPlugin.cs)
189194
- [CopilotAgentBasedPlugins](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/CopilotAgentBasedPlugins.cs)
190195
- [WebPlugins](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/WebPlugins.cs)

dotnet/src/Functions/Functions.Prompty/Functions.Prompty.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<ProjectReference Include="..\..\Extensions\PromptTemplates.Liquid\PromptTemplates.Liquid.csproj" />
2020
<ProjectReference Include="..\..\SemanticKernel.Core\SemanticKernel.Core.csproj" />
2121
<PackageReference Include="Prompty.Core" />
22+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
2223
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" />
2324
</ItemGroup>
2425
</Project>

dotnet/src/Plugins/Plugins.MsGraph/CalendarPlugin.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public sealed class CalendarPlugin
2222
{
2323
private readonly ICalendarConnector _connector;
2424
private readonly ILogger _logger;
25+
private readonly JsonSerializerOptions? _jsonSerializerOptions;
2526
private static readonly JsonSerializerOptions s_options = new()
2627
{
2728
WriteIndented = false,
@@ -34,10 +35,13 @@ public sealed class CalendarPlugin
3435
/// </summary>
3536
/// <param name="connector">Calendar connector.</param>
3637
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use for logging. If null, no logging will be performed.</param>
37-
public CalendarPlugin(ICalendarConnector connector, ILoggerFactory? loggerFactory = null)
38+
/// <param name="jsonSerializerOptions">The <see cref="JsonSerializerOptions"/> to use for serialization. If null, default options will be used.</param>
39+
public CalendarPlugin(ICalendarConnector connector, ILoggerFactory? loggerFactory = null, JsonSerializerOptions? jsonSerializerOptions = null)
3840
{
3941
Ensure.NotNull(connector, nameof(connector));
4042

43+
this._jsonSerializerOptions = jsonSerializerOptions ?? s_options;
44+
4145
this._connector = connector;
4246
this._logger = loggerFactory?.CreateLogger(typeof(CalendarPlugin)) ?? NullLogger.Instance;
4347
}
@@ -87,13 +91,13 @@ public async Task<string> GetCalendarEventsAsync(
8791

8892
const string SelectString = "start,subject,organizer,location";
8993

90-
IEnumerable<CalendarEvent> events = await this._connector.GetEventsAsync(
94+
IEnumerable<CalendarEvent>? events = await this._connector.GetEventsAsync(
9195
top: maxResults,
9296
skip: skip,
9397
select: SelectString,
9498
cancellationToken
9599
).ConfigureAwait(false);
96100

97-
return JsonSerializer.Serialize(value: events, options: s_options);
101+
return JsonSerializer.Serialize(value: events, options: this._jsonSerializerOptions);
98102
}
99103
}

dotnet/src/Plugins/Plugins.MsGraph/CloudDrivePlugin.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ public CloudDrivePlugin(ICloudDriveConnector connector, ILoggerFactory? loggerFa
3939
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
4040
/// <returns>A string containing the file content.</returns>
4141
[KernelFunction, Description("Get the contents of a file in a cloud drive.")]
42-
public async Task<string> GetFileContentAsync(
42+
public async Task<string?> GetFileContentAsync(
4343
[Description("Path to file")] string filePath,
4444
CancellationToken cancellationToken = default)
4545
{
4646
this._logger.LogDebug("Getting file content for '{0}'", filePath);
47-
Stream fileContentStream = await this._connector.GetFileContentStreamAsync(filePath, cancellationToken).ConfigureAwait(false);
47+
Stream? fileContentStream = await this._connector.GetFileContentStreamAsync(filePath, cancellationToken).ConfigureAwait(false);
48+
49+
if (fileContentStream is null)
50+
{
51+
this._logger.LogDebug("File content stream for '{0}' is null", filePath);
52+
return null;
53+
}
4854

4955
using StreamReader sr = new(fileContentStream);
5056
return await sr.ReadToEndAsync(

0 commit comments

Comments
 (0)