Skip to content

Anchored rules never match when the scan root is relative #103

Description

@Muawiya-contact

Anchored rules only fire when the scan root is absolute. Give the same
directory a relative path and every rule that starts with / stops
matching, so the files come back unknown and report::build drops
them.

The same file, twice:

$ diskern scan /var/tmp --top 2
Scanned 1 files.
Reclaimable: 3.0 MB across 1 findings and 0 duplicate sets.

Review first — 1 finding · 3.0 MB
  Temporary files · 1 · 3.0 MB
       3.0 MB  /var/tmp/build-9a2f/out.o
               matched rule temp-dirs: Temporary files. Usually safe once no program is using them.

$ cd /var && diskern scan tmp --top 2
Scanned 1 files.
Reclaimable: 0 B across 0 findings and 0 duplicate sets.

$ cd /var/tmp && diskern scan . --top 2
Scanned 1 files.
Reclaimable: 0 B across 0 findings and 0 duplicate sets.

jwalk yields paths built from the root as it was given, so the entries
are tmp/build-9a2f/out.o and ./build-9a2f/out.o. normalize only
lowercases and swaps separators, so /tmp/**, /var/tmp/**,
/private/var/tmp/** and /var/log/** — every pattern anchored at the
filesystem root — cannot match them.

Scanned 1 files is the tell: the walk found the file, the rules just
couldn't see where it was. It is the #82 failure in a different shape —
a plausible-looking empty result rather than an error — and it is worse
for --json, where nothing in the report says the paths were relative.

This is not new. Anchoring arrived in #41 and /tmp/** has behaved this
way since; #93 extends the same shape to var/tmp, which is what made it
worth writing down.

The fix is to make roots absolute before the walk, so patterns see the
path the rules were written against. std::path::absolute is the
conservative choice — it resolves . and relative prefixes without
touching the filesystem or following symlinks, which matters because
fs::canonicalize would rewrite /var/tmp to /private/var/tmp on
macOS and quietly change what the user asked to scan.

Two things worth deciding before implementing:

  • Where. Doing it in scanner::scan covers the app as well as the
    CLI; doing it in the CLI leaves the engine taking roots exactly as
    given. The engine is the one that owns what a path means, so it is
    probably the right home.
  • What it changes downstream. FileEntry.path would become
    absolute, and that path is what actions::quarantine records in the
    manifest. Absolute is the safer thing to store there — a relative
    original cannot be restored from a different working directory — so
    this likely fixes a second problem, but it deserves a test rather than
    an assumption.

A case in scanner.rs covering a relative root, and one in rules.rs
alongside rules_still_reach_the_paths_they_do_name, would pin it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclidiskern-cli: the terminal frontendenginediskern-core: scanner, rules, risk, graph, reportenhancementNew feature or requesthelp wantedExtra attention is neededlevel: intermediateNeeds familiarity with one cratepriority: mediumWorth doing, not urgent

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions