Fixed tests to check for errors, instead of crashing the restore process on path traversal checks

This commit is contained in:
Kenneth Skovhede
2026-06-16 10:20:27 +02:00
parent 4aa61b2352
commit c58087db7e
2 changed files with 31 additions and 6 deletions
@@ -1173,7 +1173,19 @@ namespace Duplicati.Library.Main.Operation
var targetfileid = restorelist.TargetFileID;
var targetfilehash = restorelist.TargetHash;
var targetfilelength = restorelist.Length;
if (await restoreDestination.FileExists(targetpath, result.TaskControl.ProgressToken).ConfigureAwait(false))
var fileExists = false;
try
{
fileExists = await restoreDestination.FileExists(targetpath, result.TaskControl.ProgressToken).ConfigureAwait(false);
}
catch (Exception ex)
{
Logging.Log.WriteWarningMessage(LOGTAG, "FileExistsFailed", ex, "Failed to check if file exists: \"{0}\", message: {1}", targetpath, ex.Message);
if (options.UnittestMode)
throw;
}
if (fileExists)
{
try
{
@@ -1208,7 +1220,7 @@ namespace Duplicati.Library.Main.Operation
{
// a file hash for verification will only be necessary if the file has exactly
// the wanted size so we have a chance to already mark the file as data-verified.
bool calcFileHash = (currentfilelength == targetfilelength);
var calcFileHash = currentfilelength == targetfilelength;
if (calcFileHash) filehasher.Initialize();
using (var file = await restoreDestination.OpenRead(targetpath, result.TaskControl.ProgressToken).ConfigureAwait(false))
@@ -16,7 +16,7 @@ namespace Duplicati.UnitTest
{
[Test]
[Category("RestoreHandler")]
public async Task RestoreToSymlinkTargetAsync()
public async Task RestoreToSymlinkTargetAsync([Values(true, false)] bool legacyRestore)
{
if (OperatingSystem.IsWindows())
Assert.Ignore("Symlink tests are not supported on Windows");
@@ -53,12 +53,25 @@ namespace Duplicati.UnitTest
var restoreOptions = new Dictionary<string, string>(this.TestOptions);
restoreOptions["restore-path"] = restoreTarget;
restoreOptions["overwrite"] = "true";
restoreOptions["restore-legacy"] = legacyRestore.ToString();
restoreOptions["unittest-mode"] = "false";
using (var c = new Controller("file://" + this.TARGETFOLDER, restoreOptions, null))
{
// We expect a UserInformationException due to path traversal detection
var ex = NUnit.Framework.Assert.ThrowsAsync<UserInformationException>(() => c.RestoreAsync(null));
NUnit.Framework.Assert.That(ex.Message.Contains("Path traversal detected"), "Expected path traversal error message");
// Verify that path traversal is detected
var restoreResults = await c.RestoreAsync(null);
var foundError = restoreResults.Errors.Any(e => e.Contains("Path traversal detected"));
if (!foundError)
{
Console.WriteLine("Errors found:");
foreach (var e in restoreResults.Errors)
Console.WriteLine(e);
Console.WriteLine("Warnings found:");
foreach (var e in restoreResults.Warnings)
Console.WriteLine(e);
}
Assert.IsTrue(foundError, "Expected path traversal error message");
}
// 5. Verify vulnerability