diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets
index 1ff0d9030aea..e510aca0b463 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets
@@ -850,8 +850,8 @@ Copyright (c) .NET Foundation. All rights reserved.
%(Content.TargetPath)
%(Content.Link)
- $([MSBuild]::MakeRelative(%(Content.DefiningProjectDirectory), %(Content.FullPath)))
- $([MSBuild]::MakeRelative($(MSBuildProjectDirectory), %(Content.FullPath)))
+
+ $([MSBuild]::MakeRelative($(MSBuildProjectDirectory), %(Content.FullPath)))
diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishWithIfDifferent.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishWithIfDifferent.cs
index 9ebb72c1b982..d234ec586284 100644
--- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishWithIfDifferent.cs
+++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishWithIfDifferent.cs
@@ -381,5 +381,79 @@ public void It_handles_IfDifferent_with_self_contained_publish()
publishDirectory.Should().HaveFile("appdata.txt");
File.ReadAllText(Path.Combine(publishDirectory.FullName, "appdata.txt")).Should().Be("Application data");
}
+
+ [Fact]
+ public void It_publishes_content_from_imported_targets_with_correct_path()
+ {
+ // This test verifies that Content items introduced from imported .targets files
+ // (where DefiningProjectDirectory differs from MSBuildProjectDirectory) are
+ // published with the correct project-relative path and do not escape the publish directory.
+ //
+ // The bug scenario: when a .targets file OUTSIDE the project directory adds a Content item,
+ // using DefiningProjectDirectory to compute the relative path can result in paths with '..'
+ // segments that escape the publish directory.
+
+ var testProject = new TestProject()
+ {
+ Name = "PublishImportedContent",
+ TargetFrameworks = ToolsetInfo.CurrentTargetFramework,
+ IsExe = true
+ };
+
+ testProject.SourceFiles["Program.cs"] = "class Program { static void Main() { } }";
+
+ var testAsset = _testAssetsManager.CreateTestProject(testProject);
+
+ var projectDirectory = Path.Combine(testAsset.Path, testProject.Name);
+
+ // Create the imported targets file OUTSIDE the project directory (sibling folder)
+ // This is the key difference - DefiningProjectDirectory will be different from MSBuildProjectDirectory
+ var externalImportsDir = Path.Combine(testAsset.Path, "ExternalImports");
+ Directory.CreateDirectory(externalImportsDir);
+
+ // Create the content file in the project directory (where we want it to be published from)
+ var contentFile = Path.Combine(projectDirectory, "project-content.txt");
+ File.WriteAllText(contentFile, "Content defined by external targets");
+
+ // Create an imported .targets file OUTSIDE the project that adds a Content item
+ // pointing to a file in the project directory. The issue is that DefiningProjectDirectory
+ // will be ExternalImports/, not the project directory.
+ var importedTargetsFile = Path.Combine(externalImportsDir, "ImportedContent.targets");
+ File.WriteAllText(importedTargetsFile, $@"
+
+
+
+
+");
+
+ // Update the main project file to import the external targets
+ var projectFile = Path.Combine(projectDirectory, $"{testProject.Name}.csproj");
+ var projectContent = File.ReadAllText(projectFile);
+ projectContent = projectContent.Replace("", @"
+
+");
+ File.WriteAllText(projectFile, projectContent);
+
+ var publishCommand = new PublishCommand(testAsset);
+ var publishResult = publishCommand.Execute();
+
+ publishResult.Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory(testProject.TargetFrameworks);
+
+ // The content file should be published with a simple filename, not with path segments
+ // that could escape the publish directory (e.g., "..\PublishImportedContent\project-content.txt")
+ publishDirectory.Should().HaveFile("project-content.txt");
+
+ // Verify the content is correct
+ var publishedContentPath = Path.Combine(publishDirectory.FullName, "project-content.txt");
+ File.ReadAllText(publishedContentPath).Should().Be("Content defined by external targets");
+
+ // Ensure no files escaped to parent directories
+ var parentDir = Directory.GetParent(publishDirectory.FullName);
+ var potentialEscapedFiles = Directory.GetFiles(parentDir.FullName, "project-content.txt", SearchOption.AllDirectories)
+ .Where(f => !f.StartsWith(publishDirectory.FullName));
+ potentialEscapedFiles.Should().BeEmpty("Content file should not escape to directories outside publish folder");
+ }
}
}