From e3b7d4a23602851c60f604e933ad5bdd1dcf9e40 Mon Sep 17 00:00:00 2001 From: eunwoo song Date: Mon, 7 Sep 2026 04:16:42 +0900 Subject: [PATCH] fix(rules): anchor system var tmp paths The recursive var/tmp glob also matched user projects and Homebrew state, exposing them as actionable temporary files. Restrict the rule to the Linux and macOS system roots and pin both intended and excluded paths in tests. --- CHANGELOG.md | 1 + crates/diskern-core/rules/base.json | 2 +- crates/diskern-core/src/rules.rs | 8 ++++++-- docs/RULES.md | 7 ++++--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96bfe77..77aa8d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ All notable changes to Diskern are documented here. The format follows ### Fixed +- The system temp rule no longer reaches user and project `var/tmp` directories - Restoring a quarantined file across filesystems no longer fails with `EXDEV` - Restore refuses when something is already at the original path, rather diff --git a/crates/diskern-core/rules/base.json b/crates/diskern-core/rules/base.json index d391a38..090c65b 100644 --- a/crates/diskern-core/rules/base.json +++ b/crates/diskern-core/rules/base.json @@ -87,7 +87,7 @@ }, { "id": "temp-dirs", - "patterns": ["/tmp/**", "**/var/tmp/**", "**/appdata/local/temp/**"], + "patterns": ["/tmp/**", "/var/tmp/**", "/private/var/tmp/**", "**/appdata/local/temp/**"], "category": "temp_file", "verdict": "review", "description": "Temporary files. Usually safe once no program is using them." diff --git a/crates/diskern-core/src/rules.rs b/crates/diskern-core/src/rules.rs index 2cc81dc..a7368a5 100644 --- a/crates/diskern-core/src/rules.rs +++ b/crates/diskern-core/src/rules.rs @@ -229,8 +229,11 @@ mod tests { fn rules_do_not_reach_outside_the_paths_they_name() { let db = RulesDb::embedded(); for path in [ - "/home/user/tmp/tax-return.pdf", // not /tmp - "/home/user/var/log/notes.txt", // not /var/log + "/home/user/tmp/tax-return.pdf", // not /tmp + "/home/user/var/log/notes.txt", // not /var/log + "/home/user/var/tmp/notes.txt", // not /var/tmp + "/home/user/project/var/tmp/session.dat", + "/opt/homebrew/var/tmp/formula.lock", "/home/user/Downloads/holiday.dmgx", // not a .dmg "/home/user/mytmp/scratch.bin", ] { @@ -246,6 +249,7 @@ mod tests { for (path, expected) in [ ("/tmp/build-9a2f/out.o", Category::TempFile), ("/var/tmp/systemd-private/x", Category::TempFile), + ("/private/var/tmp/com.apple.launchd/x", Category::TempFile), ( "C:\\Users\\x\\AppData\\Local\\Temp\\a.tmp", Category::TempFile, diff --git a/docs/RULES.md b/docs/RULES.md index 50e1949..f4823e1 100644 --- a/docs/RULES.md +++ b/docs/RULES.md @@ -48,9 +48,10 @@ evidence (e.g. recently-accessed files), never less. - a pattern that starts with `/` is anchored at the filesystem root That anchoring is what keeps a rule inside the directory it names. -`/tmp/**` is the root's scratch directory; it does not reach -`/home/user/tmp/tax-return.pdf`. `**/node_modules/**` still matches at -any depth, because that is what the rule means. +`/tmp/**` and `/var/tmp/**` are root scratch directories; they do not reach +`/home/user/tmp/tax-return.pdf` or a project's `var/tmp`. macOS's corresponding +system path is `/private/var/tmp/**`. `**/node_modules/**` still matches at any +depth, because that is what the rule means. Write patterns to end in `/**` when the rule is about a directory, and as `**/*.ext` when it is about an extension. A directory pattern without