using Microsoft.Extensions.Configuration; using w4c_workflows.Services.Execution; using Xunit; namespace w4c_workflows.Tests; /// /// Entry-file containment: a task must never be able to execute (or read) a file /// outside its own working directory, whether via an absolute path or a /// .. escape. /// public class EntryPathContainmentTests { private static TaskInvocation Invocation(string entryFile, string workingDir) => new( TaskInvocation.TypeValue, "run-1", "task-1", "key", "shell", entryFile, null, new Dictionary(), null, workingDir, "tenant-1", 1); private static SubprocessScriptExecutor Executor() => new("shell", "sh", new ConfigurationBuilder().Build()); [Fact] public async Task Absolute_entry_file_is_rejected() { var result = await Executor().ExecuteAsync(Invocation("/etc/passwd", Path.GetTempPath()), default); Assert.False(result.Success); Assert.Contains("must be relative", result.Error); } [Fact] public async Task Entry_file_escaping_the_working_directory_is_rejected() { var dir = Directory.CreateTempSubdirectory("w4c-contain-"); try { var result = await Executor().ExecuteAsync(Invocation("../outside.sh", dir.FullName), default); Assert.False(result.Success); Assert.Contains("escapes", result.Error); } finally { dir.Delete(recursive: true); } } }