diff --git a/src/lib/server/backup.test.ts b/src/lib/server/backup.test.ts index a60a644..869f12d 100644 --- a/src/lib/server/backup.test.ts +++ b/src/lib/server/backup.test.ts @@ -50,6 +50,24 @@ describe("backup", () => { expect(listing).not.toContain("stale.txt"); }); + it("excludes *.tmp files from the archive", async () => { + fs.writeFileSync(path.join(dataDir, "scratch.tmp"), "tmp"); + fs.writeFileSync(path.join(dataDir, "keep.json"), "{}"); + fs.writeFileSync(path.join(backendDir, "session.tmp"), "tmp"); + fs.writeFileSync(path.join(backendDir, "notes.md"), "notes"); + + const entry = await backup.createBackup("manual"); + + const listing = execFileSync("tar", [ + "-tzf", + path.join(backup.backupsDir(), entry.name), + ]).toString(); + expect(listing).toContain("keep.json"); + expect(listing).toContain("notes.md"); + expect(listing).not.toContain("scratch.tmp"); + expect(listing).not.toContain("session.tmp"); + }); + it("validates names and rejects traversal", () => { expect(backup.isValidBackupName("backup-20260811T073000-auto.tar.gz")).toBe(true); expect(backup.isValidBackupName("../etc/passwd")).toBe(false); diff --git a/src/lib/server/backup.ts b/src/lib/server/backup.ts index 812f4be..18bc76a 100644 --- a/src/lib/server/backup.ts +++ b/src/lib/server/backup.ts @@ -67,13 +67,17 @@ async function runBackup(origin: "manual" | "auto"): Promise { const args = [ "-czf", out, "--exclude", `${base}/backups`, - "-C", path.dirname(dataDir), base, + "--exclude", `${base}/*.tmp`, ]; const backend = config.backup.backendDataDir.trim(); if (backend) { if (!fs.existsSync(backend)) { throw new Error(`Backend data directory does not exist: ${backend}`); } + args.push("--exclude", `${path.basename(backend)}/*.tmp`); + } + args.push("-C", path.dirname(dataDir), base); + if (backend) { args.push("-C", path.dirname(backend), path.basename(backend)); } try {