Skip to content

🐛 avoid scanning the filesystem root for commit-only OSV lookups - #5180

Open
pujitha24 wants to merge 4 commits into
ossf:mainfrom
pujitha24:auto/issue-5056
Open

🐛 avoid scanning the filesystem root for commit-only OSV lookups#5180
pujitha24 wants to merge 4 commits into
ossf:mainfrom
pujitha24:auto/issue-5056

Conversation

@pujitha24

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

Bug fix: the Vulnerabilities check crashes for repositories that have no local
on-disk checkout (currently only the GitLab client), because osv-scanner
falls back to scanning the entire filesystem root and hits permission errors
on restricted paths such as /proc.

What is the current behavior?

For clients whose RepoClient.LocalPath() returns an empty string (only
clients/gitlabrepo today), clients/osv.go calls osvscanner.DoScan with a
non-empty GitCommits but an empty DirectoryPaths. In google/osv-scanner
v2.3.2 (bumped in v5.5.0, previously v2.2.4), that specific combination makes
DoScan default to scanning the filesystem root / with the default
lockfile/sbom/directory extractors, since osvscanner's scan() sets
rootMap = map[string][]string{"/": {}} whenever no directories were given
but commits were. On typical Linux hosts this walk hits /proc and fails
with a permission error, which scorecard surfaces as a hard check failure:

Check Vulnerabilities failed for <gitlab-repo>: internal error: vulnerabilitiesClient.ListUnfixedVulnerabilities: osvscanner.DoScan: open proc/tty/driver/.gitignore: permission denied

This makes scorecard --repo=<gitlab-url> fail entirely unless the caller
explicitly excludes the Vulnerabilities check.

What is the new behavior (if this is a feature change)?

When there's a commit to scan but no local directory, clients/osv.go now
creates a harmless empty temporary directory and passes that to
DirectoryPaths instead of leaving it empty. This prevents osv-scanner's
rootMap from defaulting to /, while still running the git-commit-based
OSV lookup correctly: osv-scanner's gitcommitdirect extractor is a
"standalone" extractor that returns results purely from the configured
commit list and ignores whatever directory it's associated with, so no
scanning functionality is lost, only the unintended full-filesystem walk is
avoided. The temporary directory is removed after the scan.

  • Tests for the changes have been added (for bug fixes/features)

Which issue(s) this PR fixes

NONE

Special notes for your reviewer

This works around a behavior change in google/osv-scanner v2.3.2 (the
version bump landed in scorecard v5.5.0): in v2.2.4, a GitCommits-only scan
(no DirectoryPaths) was handled by an independent code path that never
touched the filesystem. v2.3.2 refactored this into the same directory-walk
loop used for lockfile/SBOM scanning, and defaults to / when no directories
are supplied. This scorecard-side fix avoids triggering that fallback rather
than changing osv-scanner itself.

Validation performed locally (this repo requires go test/golangci-lint
per CONTRIBUTING.md; no e2e/live-cluster run applies to this change):

  • Added clients.TestCommitOnlyNoLocalPath, which calls
    ListUnfixedVulnerabilities with a commit and an empty local path. I
    confirmed it reproduces the exact reported failure (a permission-denied
    error scanning a restricted path) against the pre-fix code, and passes
    after the fix.
  • go build ./...
  • go test ./clients/... ./checks/... ./checker/... — all pass (one
    pre-existing, unrelated failure in clients/githubrepo due to a missing
    TOKEN_TYPE env var in this sandbox, reproduced identically on main
    before this change).
  • go vet ./clients/...
  • golangci-lint run -c .golangci.yml ./clients/... — 0 new issues
    (--new-from-rev=HEAD reports 0 issues; pre-existing goconst findings in
    unrelated files are unchanged).

Does this PR introduce a user-facing change?

Fixed a bug where the Vulnerabilities check could crash with a permission
error for repositories scanned without a local checkout (for example,
GitLab repositories), instead of correctly reporting vulnerability data.

Fixes #5056

Motivation:
The Vulnerabilities check crashes for repositories with no local on-disk
checkout (currently only the GitLab client, whose RepoClient.LocalPath()
always returns an empty string). clients/osv.go calls osvscanner.DoScan with
a non-empty GitCommits but empty DirectoryPaths in that case. In
google/osv-scanner v2.3.2 (bumped in scorecard v5.5.0, from v2.2.4), that
combination makes DoScan default to scanning the filesystem root "/" with
the default lockfile/sbom/directory extractors, since v2.3.2 folded
commit-only scanning into the same directory-walk loop used for lockfile
scanning and falls back to "/" when no directories were supplied. On a
typical Linux host this walk hits /proc and fails with a permission error,
which scorecard surfaces as a hard check failure, breaking
`scorecard --repo=<gitlab-url>` entirely unless the Vulnerabilities check is
explicitly excluded.

Report: ossf#5056

Approach:
When there's a commit to scan but no local directory, create a harmless
empty temporary directory and pass it as DirectoryPaths instead of leaving
it empty. This keeps osv-scanner's rootMap from defaulting to "/". The
git-commit-based lookup still runs correctly: osv-scanner's gitcommitdirect
extractor is a standalone extractor that returns results purely from the
configured commit list and ignores whatever directory it's paired with, so
no scanning functionality is lost, only the unintended full-filesystem walk
is avoided. The temporary directory is removed after the scan.

Validation:
Added clients.TestCommitOnlyNoLocalPath, calling ListUnfixedVulnerabilities
with a commit and an empty local path. Confirmed it reproduces the exact
reported failure (a permission-denied error scanning a restricted path)
against the pre-fix code, and passes after the fix:
  go test ./clients/ -run TestCommitOnlyNoLocalPath -v
Also ran, all passing (one pre-existing, unrelated failure in
clients/githubrepo from a missing TOKEN_TYPE env var in this sandbox,
reproduced identically on main before this change):
  go build ./...
  go test ./clients/... ./checks/... ./checker/...
  go vet ./clients/...
  golangci-lint run -c .golangci.yml ./clients/...   (0 new issues)

Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
@pujitha24
pujitha24 requested a review from a team as a code owner August 14, 2026 08:27
@pujitha24
pujitha24 requested review from AdamKorcz and justaugustus and removed request for a team August 14, 2026 08:27
@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Aug 14, 2026
TestCommitOnlyNoLocalPath was marked t.Parallel(), which let it run
concurrently with TestEmptyProject. Both call
ListUnfixedVulnerabilities, which invokes osv-scanner's SetLogger, a
package-level function that writes to an unsynchronized global. That
tripped the -race detector in CI (unit-test, integration-trusted,
gitlab-integration-trusted). Dropping t.Parallel() from the new test
serializes the two calls and eliminates the race.

Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.12%. Comparing base (353ed60) to head (2ac1a64).
⚠️ Report is 373 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5180      +/-   ##
==========================================
+ Coverage   66.80%   70.12%   +3.31%     
==========================================
  Files         230      252      +22     
  Lines       16602    15868     -734     
==========================================
+ Hits        11091    11127      +36     
+ Misses       4808     3856     -952     
- Partials      703      885     +182     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

TestCommitOnlyNoLocalPath can't run in parallel (osv-scanner's SetLogger
writes to a shared global, tripping the race detector against
TestEmptyProject), but the paralleltest linter still flags it. Add a
nolint directive with a reason, matching existing precedent in this repo.

Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

BUG - Scorecard version v5.5.0 doesn't work anymore with GitLab projects

1 participant