fix(sandbox): unique backup names to prevent same-basename collision (#64)

Backups were named workingDir/${fileName}.bak — two affected paths with the
same filename in different dirs overwrote each other's backup, so failure
restore wrote the wrong content. Name by full-path hash. Latent today
(single-path tools) but a correctness landmine for any multi-path tool.
This commit is contained in:
2026-07-12 12:38:27 +04:00
parent cf856742b1
commit 8ef957cd53
@@ -119,7 +119,12 @@ class SandboxedToolExecutor(
for (original in affectedPaths) {
// A1: skip files that don't yet exist (new-file tools have nothing to back up)
if (!Files.exists(original)) continue
val backupPath = workingDir.resolve("${original.fileName}.bak")
// Name the backup by the full source path, not just the basename — two affected paths
// sharing a filename in different dirs would otherwise overwrite each other's backup and
// restore the wrong content on failure. Hash keeps the name filesystem-safe and unique.
val stem = original.fileName.toString()
val hash = Integer.toHexString(original.toAbsolutePath().normalize().toString().hashCode())
val backupPath = workingDir.resolve("$stem.$hash.bak")
Files.copy(original, backupPath, StandardCopyOption.REPLACE_EXISTING)
put(original, backupPath)
}