Skip to content

Report unreadable files as a partial scan instead of silent success - #2235

Open
hamodywe wants to merge 1 commit into
gitleaks:masterfrom
hamodywe:fix/unreadable-file-partial-scan
Open

hamodywe wants to merge 1 commit into
gitleaks:masterfrom
hamodywe:fix/unreadable-file-partial-scan

Conversation

@hamodywe

@hamodywe hamodywe commented Aug 8, 2026

Copy link
Copy Markdown

When os.Open fails for a scan target, Fragments logged a warning only for permission-denied and otherwise stayed completely silent, then returned nil regardless -- so a scan that silently missed a file still printed "no leaks found" and exited 0. The partial-scan machinery in cmd/root.go (the "no leaks found in partial scan" message and exit 1) already exists for exactly this situation but was unreachable, because nothing on this path ever produced a non-nil error.

Adds an atomic counter to Files, incremented whenever a scan target can't be opened for any reason (not just permission-denied, which is now logged with the actual error instead of a generic message). After the scan completes, the count is folded into the returned error via the new withUnreadableFilesError helper, joined with any existing walk error, so the caller's partial-scan handling now actually fires.

Tests:

  • sources/files_test.go: TestFiles_withUnreadableFilesError covers the helper directly (no unreadable files, unreadable files alone, and combined with an existing walk error) -- portable, no filesystem permissions involved.
  • detect/detect_test.go: TestDetectSkipsUnreadableFileAndReportsPartialScan is an end-to-end regression through the real DetectSource path: one readable file with a real secret, one chmod 0000 file in the same directory. Asserts the readable file's finding still surfaces (an unreadable sibling doesn't take down the whole scan) and the returned error mentions the skipped file. Skipped on Windows/root, following the same pattern already used by TestDetectWithSymlinks -- chmod-based permission denial isn't portable to either.

Verified go build/go vet clean, sources package tests pass in full (including on Windows, where this was developed), and the Windows-only detect-level test correctly registers and skips rather than silently not running.

Fixes #2232

Description:

Explain the purpose of the PR.

Checklist:

  • Does your PR pass tests?
  • Have you written new tests for your changes?
  • Have you lint your code locally prior to submission?

When os.Open fails for a scan target, Fragments logged a warning only
for permission-denied and otherwise stayed completely silent, then
returned nil regardless -- so a scan that silently missed a file still
printed "no leaks found" and exited 0. The partial-scan machinery in
cmd/root.go (the "no leaks found in partial scan" message and exit 1)
already exists for exactly this situation but was unreachable, because
nothing on this path ever produced a non-nil error.

Adds an atomic counter to Files, incremented whenever a scan target
can't be opened for any reason (not just permission-denied, which is
now logged with the actual error instead of a generic message). After
the scan completes, the count is folded into the returned error via
the new withUnreadableFilesError helper, joined with any existing walk
error, so the caller's partial-scan handling now actually fires.

Tests:
- sources/files_test.go: TestFiles_withUnreadableFilesError covers the
  helper directly (no unreadable files, unreadable files alone, and
  combined with an existing walk error) -- portable, no filesystem
  permissions involved.
- detect/detect_test.go: TestDetectSkipsUnreadableFileAndReportsPartialScan
  is an end-to-end regression through the real DetectSource path: one
  readable file with a real secret, one chmod 0000 file in the same
  directory. Asserts the readable file's finding still surfaces (an
  unreadable sibling doesn't take down the whole scan) and the returned
  error mentions the skipped file. Skipped on Windows/root, following
  the same pattern already used by TestDetectWithSymlinks -- chmod-based
  permission denial isn't portable to either.

Verified go build/go vet clean, sources package tests pass in full
(including on Windows, where this was developed), and the Windows-only
detect-level test correctly registers and skips rather than silently
not running.

Fixes gitleaks#2232

This branch has not been deployed

No deployments
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.

Unreadable files are silently skipped and the run still reports "no leaks found" with exit 0

1 participant