Skip to content

fix(sources/filesystem): order resume comparison by path component#5041

Open
genisis0x wants to merge 1 commit into
trufflesecurity:mainfrom
genisis0x:fix-filesystem-resume-prefix-sibling
Open

fix(sources/filesystem): order resume comparison by path component#5041
genisis0x wants to merge 1 commit into
trufflesecurity:mainfrom
genisis0x:fix-filesystem-resume-prefix-sibling

Conversation

@genisis0x

@genisis0x genisis0x commented Jun 16, 2026

Copy link
Copy Markdown

Description:

Resuming a filesystem scan could silently skip an entire sibling directory when one directory name is a prefix of another (e.g. blue-team and blue-team-deprecated).

scanDir decided whether a directory was already scanned by comparing its path against the stored resume point with a raw string comparison (path < resumeAfter). Raw string order does not match the depth-first order os.ReadDir produces, because the separator / (0x2F) sorts after characters that are valid inside a path component such as - (0x2D) and . (0x2E).

So when resuming inside blue-team with resume point /root/blue-team/project-notes.txt, the check evaluated:

"/root/blue-team-deprecated" < "/root/blue-team/project-notes.txt"  // true: '-' < '/'

and skipped blue-team-deprecated entirely — every file beneath it (e.g. AWSCredentials.txt) was never enumerated or scanned. Renaming blue-team to blue-team2 made the problem disappear, matching the report.

The fix compares the two paths component by component, which matches os.ReadDir's ordering (blue-team sorts before blue-team-deprecated). The in-subtree HasPrefix checks and the per-entry loop were already correct and are unchanged.

Closes #5039

Tests:

  • TestResumptionWithPrefixSiblingDirectories — integration test reproducing the report (resume inside blue-team, assert the sibling blue-team-deprecated/AWSCredentials.txt is still scanned).
  • TestComparePathsForResume — unit test for the comparison helper, including the prefix-sibling case and the existing before/after/ancestor cases.
  • Existing TestResumption* tests still pass.

Checklist:

  • Tests passing (make test-community)?
  • Lint passing (make lint)?

Note

Medium Risk
Changes interrupted-scan resume logic in the filesystem source; a bug here could skip files and miss secrets, but the change is narrow and covered by new regression tests.

Overview
Fixes silent skipped directories when a filesystem scan resumes and sibling folder names share a prefix (e.g. blue-team vs blue-team-deprecated).

scanDir used to treat a directory as already scanned if its full path was lexicographically before the resume point (path < resumeAfter). That order disagrees with os.ReadDir depth-first traversal, because / sorts after characters like - inside a name—so …/blue-team-deprecated could look “before” …/blue-team/notes.txt and the whole sibling tree was never scanned.

The PR adds comparePathsForResume (component-by-component, then shorter path wins for ancestors) and uses it for the out-of-subtree skip decision. Integration and unit tests cover the prefix-sibling regression and existing before/after/ancestor cases.

Reviewed by Cursor Bugbot for commit d39582d. Bugbot is set up for automated code reviews on this repo. Configure here.

When resuming a filesystem scan, scanDir compared the directory path
against the stored resume point with a raw string comparison
(`path < resumeAfter`). Raw comparison does not match the depth-first
traversal order produced by os.ReadDir, because the separator '/' (0x2F)
sorts after characters that are valid inside a path component such as
'-' (0x2D) and '.' (0x2E).

So with sibling directories where one name is a prefix of the other,
e.g. `blue-team` and `blue-team-deprecated`, resuming inside `blue-team`
made scanDir evaluate `"/root/blue-team-deprecated" < "/root/blue-team/file"`
as true and skip `blue-team-deprecated` entirely, silently dropping every
file beneath it.

Compare the paths component by component instead, which matches the order
os.ReadDir returns entries in ("blue-team" before "blue-team-deprecated").

Adds an integration test for the prefix-sibling case and a unit test for
the comparison helper.

Closes trufflesecurity#5039
@genisis0x genisis0x requested a review from a team June 16, 2026 07:46
@genisis0x genisis0x requested a review from a team as a code owner June 16, 2026 07:46
@CLAassistant

CLAassistant commented Jun 16, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Filesystem Directory Transversal Issue - TruffleHog Fails to Discover Secrets

2 participants