Skip to content

Commit 4c91ca3

Browse files
authored
Ensure file-based program artifacts are restricted to the current user (#48813)
1 parent b5f3be8 commit 4c91ca3

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,19 @@ Building because previous global properties count ({previousCacheEntry.GlobalPro
362362
private void MarkBuildStart()
363363
{
364364
string directory = GetArtifactsPath();
365-
Directory.CreateDirectory(directory);
365+
366+
if (OperatingSystem.IsWindows())
367+
{
368+
Directory.CreateDirectory(directory);
369+
}
370+
else
371+
{
372+
// Ensure only the current user has access to the directory to avoid leaking the program to other users.
373+
// We don't mind that permissions might be different if the directory already exists,
374+
// since it's under user's local directory and its path should be unique.
375+
Directory.CreateDirectory(directory, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
376+
}
377+
366378
File.WriteAllText(Path.Join(directory, BuildStartCacheFileName), EntryPointFileFullPath);
367379
}
368380

test/dotnet.Tests/CommandTests/Run/RunFileTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Runtime.Versioning;
45
using System.Text.Json;
56
using Microsoft.CodeAnalysis;
67
using Microsoft.DotNet.Cli.Commands;
@@ -809,6 +810,42 @@ public void NoBuild_02()
809810
.And.HaveStdOut("Changed");
810811
}
811812

813+
[PlatformSpecificFact(TestPlatforms.AnyUnix), UnsupportedOSPlatform("windows")]
814+
public void ArtifactsDirectory_Permissions()
815+
{
816+
var testInstance = _testAssetsManager.CreateTestDirectory();
817+
var programFile = Path.Join(testInstance.Path, "Program.cs");
818+
File.WriteAllText(programFile, s_program);
819+
820+
// Remove artifacts from possible previous runs of this test.
821+
var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
822+
if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
823+
824+
new DotnetCommand(Log, "build", "Program.cs")
825+
.WithWorkingDirectory(testInstance.Path)
826+
.Execute()
827+
.Should().Pass();
828+
829+
new DirectoryInfo(artifactsDir).UnixFileMode
830+
.Should().Be(UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute, artifactsDir);
831+
832+
// Re-create directory with incorrect permissions.
833+
Directory.Delete(artifactsDir, recursive: true);
834+
Directory.CreateDirectory(artifactsDir, UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute);
835+
var actualMode = new DirectoryInfo(artifactsDir).UnixFileMode
836+
.Should().NotBe(UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute, artifactsDir).And.Subject;
837+
838+
new DotnetCommand(Log, "build", "Program.cs")
839+
.WithWorkingDirectory(testInstance.Path)
840+
.Execute()
841+
.Should().Fail()
842+
.And.HaveStdErrContaining("build-start.cache"); // Unhandled exception: Access to the path '.../build-start.cache' is denied.
843+
844+
// Build shouldn't have changed the permissions.
845+
new DirectoryInfo(artifactsDir).UnixFileMode
846+
.Should().Be(actualMode, artifactsDir);
847+
}
848+
812849
[Fact]
813850
public void LaunchProfile()
814851
{

0 commit comments

Comments
 (0)