Skip to content

fix(csharp): prevent symlink escapes in file references#401

Merged
sethjuarez merged 3 commits into
mainfrom
sejuare-microsoft-fix-csharp-symlink-resolution
Jul 20, 2026
Merged

fix(csharp): prevent symlink escapes in file references#401
sethjuarez merged 3 commits into
mainfrom
sejuare-microsoft-fix-csharp-symlink-resolution

Conversation

@sethjuarez

Copy link
Copy Markdown
Member

Summary

  • canonicalize every path component before validating \ containment
  • reject intermediate directory symlink and junction escapes in sync and async loaders
  • release the coordinated C# package set as 2.0.0-beta.4

Fixes GHSA-w28w-gp39-m4p6.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3ecadcae-f3dd-4e5f-9411-69eb69340d10
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3ecadcae-f3dd-4e5f-9411-69eb69340d10
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3ecadcae-f3dd-4e5f-9411-69eb69340d10

foreach (var component in components)
{
canonicalPath = Path.Combine(canonicalPath, component);
var root = Directory.CreateTempSubdirectory("prompty-loader-");
try
{
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
try
{
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
var externalDir = Directory.CreateDirectory(Path.Combine(root.FullName, "external"));
{
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
var externalDir = Directory.CreateDirectory(Path.Combine(root.FullName, "external"));
File.WriteAllText(Path.Combine(externalDir.FullName, "secret.txt"), "secret");
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
var externalDir = Directory.CreateDirectory(Path.Combine(root.FullName, "external"));
File.WriteAllText(Path.Combine(externalDir.FullName, "secret.txt"), "secret");
Directory.CreateSymbolicLink(Path.Combine(promptDir.FullName, "assets"), externalDir.FullName);
File.WriteAllText(Path.Combine(externalDir.FullName, "secret.txt"), "secret");
Directory.CreateSymbolicLink(Path.Combine(promptDir.FullName, "assets"), externalDir.FullName);

var prompt = Path.Combine(promptDir.FullName, "bad.prompty");
var root = Directory.CreateTempSubdirectory("prompty-loader-");
try
{
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
try
{
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
var externalDir = Directory.CreateDirectory(Path.Combine(root.FullName, "external"));
{
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
var externalDir = Directory.CreateDirectory(Path.Combine(root.FullName, "external"));
File.WriteAllText(Path.Combine(externalDir.FullName, "secret.txt"), "secret");
var promptDir = Directory.CreateDirectory(Path.Combine(root.FullName, "prompts"));
var externalDir = Directory.CreateDirectory(Path.Combine(root.FullName, "external"));
File.WriteAllText(Path.Combine(externalDir.FullName, "secret.txt"), "secret");
Directory.CreateSymbolicLink(Path.Combine(promptDir.FullName, "assets"), externalDir.FullName);
@sethjuarez
sethjuarez merged commit 70912ce into main Jul 20, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant