Skip to content

feat: add --exclude flag to skip paths during scanning#2458

Merged
another-rex merged 32 commits intogoogle:mainfrom
Ankitsinghsisodya:feat/exclude-paths-flag
Feb 11, 2026
Merged

feat: add --exclude flag to skip paths during scanning#2458
another-rex merged 32 commits intogoogle:mainfrom
Ankitsinghsisodya:feat/exclude-paths-flag

Conversation

@Ankitsinghsisodya
Copy link
Copy Markdown
Contributor

Overview

Issue: #2324

This PR adds a --exclude CLI flag that allows users to specify glob patterns to exclude files and directories from vulnerability scanning.

Fixes #2324

Details

Problem

Users scanning large repositories often want to exclude test files, documentation, and other non-production code from vulnerability scans. While .gitignore is respected by default and osv-scanner.toml can be used, there was no quick CLI option to exclude paths.

Solution

Added --exclude / -e flag that accepts glob patterns:

osv-scanner scan source -r --exclude="**/test/**" --exclude="**/docs/**" ./path

Add --exclude/-e CLI flag that accepts glob patterns to exclude
files and directories from vulnerability scanning. This addresses
user requests to easily skip test files and documentation during scans.

Changes:
- Add ExcludePatterns field to ScannerActions struct
- Add --exclude flag to scan source command
- Wire ExcludePatterns to scalibr's SkipDirGlob option
- Document the new flag in scan-source.md

Fixes google#2324
Copy link
Copy Markdown
Collaborator

@another-rex another-rex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely something we want, though might need a bit more design before including it. It is really hard for us to justify removing a flag once it's added.

I want a way for people to specify regex patterns without having to add another separate flag. Maybe something like if it is wrapped /<regex>/ like in javascript?

- Replace regexp import with cachedregexp to satisfy depguard rules
- Add Regexp type alias and Compile function to cachedregexp package
- Remove duplicate package doc comment (godoclint)
- Add blank line before return (nlreturn)
- Add t.Parallel() calls to test functions (paralleltest)
Copy link
Copy Markdown
Collaborator

@G-Rath G-Rath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate your work on this!

Could you please:

  • move the flag to be --experimental- (this is mainly because right now scalibr only supports skipping directories, not files which'll hopefully be able to change but in the meantime this will mean we can do breaking changes if we go another direction instead)
  • update the docs to reflect that this only applies to directories, not files
  • add a couple of cmd tests
  • update the syntax to use :, matching our --lockfile flag, which'll also let us use DirsToSkip too
    • if the string is prefixed with : or nothing, it should be applied as a directory (DirsToSkip)
    • if the string is prefixed with g:, it should be applied as a glob (SkipDirGlob)
    • if the string is prefixed with r:, it should be applied as a regex (SkipDirRegex)

Comment thread internal/cachedregexp/regex.go Outdated
@another-rex
Copy link
Copy Markdown
Collaborator

another-rex commented Jan 20, 2026

if the string is prefixed with :, it should be applied as a directory (DirsToSkip)

to clarify, also if it is not prefixed, use DirsToSkip, the prefixing with : is just an escape hatch incase your file path itself has a : inside.

@Ankitsinghsisodya
Copy link
Copy Markdown
Contributor Author

@another-rex sir, I have done the changes suggested you.

Comment thread internal/cachedregexp/regex.go Outdated
Comment thread pkg/osvscanner/osvscanner.go Outdated
Comment thread pkg/osvscanner/scan.go Outdated
Comment thread pkg/osvscanner/scan.go Outdated
Comment thread pkg/osvscanner/exclude_test.go
Comment thread pkg/osvscanner/exclude.go
Comment thread cmd/osv-scanner/mcp/integration_test.go
@Ankitsinghsisodya
Copy link
Copy Markdown
Contributor Author

I initially removed the type alias as you suggested, but CI failed with a depguard error:

import 'regexp' is not allowed from list 'regexp':
Use github.com/google/osv-scanner/v2/internal/cachedregexp instead (depguard)

The exclude.go file needs the *regexp.Regexp type for the struct field, but can't import regexp directly due to the lint rule. Adding the type alias back in cachedregexp allows other packages to use *cachedregexp.Regexp without violating depguard.

Should I look into adding an exception to the depguard config for this file, or is the type alias acceptable given this constraint?

@G-Rath
Copy link
Copy Markdown
Collaborator

G-Rath commented Jan 20, 2026

right yeah of course - I think for now let's go with adding the exception as that mirrors what we're doing elsewhere for this situation, though I think I'll revisit that after this as it'll probably be better to just re-export stuff from cachedregexp and/or try to use the forbidigo linter instead

(I had forgotten we pretty much don't use regexp outside of cachedregexp.MustCompile 😅)

G-Rath
G-Rath previously requested changes Jan 20, 2026
Copy link
Copy Markdown
Collaborator

@G-Rath G-Rath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good, we just also do want to change the cmd flag to use exclude too

Comment thread cmd/osv-scanner/scan/source/command.go Outdated
Comment thread cmd/osv-scanner/scan/source/command_test.go Outdated
Comment thread pkg/osvscanner/exclude_test.go Outdated
Comment thread pkg/osvscanner/exclude_test.go Outdated
Comment thread pkg/osvscanner/exclude_test.go
@G-Rath G-Rath assigned G-Rath and unassigned G-Rath Jan 20, 2026
Ankitsinghsisodya and others added 4 commits January 21, 2026 01:59
Co-authored-by: Gareth Jones <3151613+G-Rath@users.noreply.github.com>
Co-authored-by: Gareth Jones <3151613+G-Rath@users.noreply.github.com>
…e` and update its usage and documentation.
Copy link
Copy Markdown
Collaborator

@another-rex another-rex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Comment thread cmd/osv-scanner/scan/source/command.go Outdated
@another-rex
Copy link
Copy Markdown
Collaborator

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new experimental flag --experimental-exclude to allow excluding paths from scanning. The implementation is well-structured, with new logic for parsing exclusion patterns, comprehensive tests, and clear documentation. I've found one issue with how absolute paths are handled, which could lead to silent failures. My detailed feedback is in the review comments. Also, note that the PR description and title mention --exclude, but the implementation uses --experimental-exclude, which is correctly reflected in the documentation.

Comment thread pkg/osvscanner/exclude.go
@another-rex
Copy link
Copy Markdown
Collaborator

Hmm the requested interactions not found errors are a bit odd in the CI, because it looks like you have added the new interactions to the cassettes. @G-Rath Can you take a look at why that could be happening?

@G-Rath
Copy link
Copy Markdown
Collaborator

G-Rath commented Jan 21, 2026

I think they might just need to be regenerated, as they're still using the old X-Test-Name and it doesn't look like there are interactions for the exclude_with_multiple_exact_directories and exclude_with_multiple_pattern_types tests.

First I'd do is just revert all changes to cmd/osv-scanner/scan/source/testdata/cassettes/TestCommand.yaml, re-run the suite, and commit the results

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jan 29, 2026

Codecov Report

❌ Patch coverage is 90.76923% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.76%. Comparing base (f9a43d6) to head (11257de).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/osvscanner/exclude.go 91.66% 2 Missing and 2 partials ⚠️
internal/cachedregexp/regex.go 77.77% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2458      +/-   ##
==========================================
+ Coverage   67.72%   67.76%   +0.03%     
==========================================
  Files         172      173       +1     
  Lines       13343    13414      +71     
==========================================
+ Hits         9037     9090      +53     
- Misses       3592     3604      +12     
- Partials      714      720       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 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.

@another-rex
Copy link
Copy Markdown
Collaborator

Apologies for the delay, tests are mostly passing now, though there does seem to be a legitimate issue on Windows.

Is it easy for you to test on Windows to debug this? Otherwise we can look into it when we have time available.

@Ankitsinghsisodya
Copy link
Copy Markdown
Contributor Author

Ankitsinghsisodya commented Jan 29, 2026

@another-rex Sorry to say but I can only test on macos and Linux(ubuntu).

@another-rex
Copy link
Copy Markdown
Collaborator

@G-Rath Can you take a look at the windows error and see if it can be resolved easily?

Comment thread pkg/osvscanner/exclude.go Outdated
// Unknown prefixes are returned as-is so the caller can provide appropriate error messages.
func parseExcludeArg(arg string) (string, string) {
// Handle Windows absolute paths (e.g., C:\path)
if runtime.GOOS == "windows" && filepath.IsAbs(arg) {
Copy link
Copy Markdown
Collaborator

@G-Rath G-Rath Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@another-rex this is why Windows is unhappy, because r:/ and g:/ are absolute paths on Windows

Solutions that come to mind are:

  1. we assume a lowercase r and g are our prefixes
    • Windows drive letters are case-insensitive and usually represented in uppercase
  2. we have a double colon rule (i.e. have both r::/ and r:/ be valid)
    • yuck, and yet more of a bandaid
  3. we make it a requirement to prefix with : if you're doing absolute paths, at least on Windows
    • this'd be inconsistent with our logic elsewhere, though we could change that too..
  4. we change the symbol
    • : feels like the most intuitive symbol to me though for us to be using 😞
  5. we explicitly check for r: and g:, and say Windows users have to prefix with : if they want to pass in those driver letters in lowercase
  6. we do nothing (at least for now), and tell people their regexps need to start with something e.g. .*

Those last two seem like the most straightforward for the time being (given this is experimental and all)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 5 is probably the best way to go here, and on windows just force uppercase to be used for drive names if they want to have drive r: or drive g: to be interpreted as drives.

@another-rex another-rex enabled auto-merge (squash) February 9, 2026 03:13
@another-rex another-rex merged commit 2a19389 into google:main Feb 11, 2026
18 checks passed
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.

Option to skip or ignore files and folder while scanning for Vulnerabilities

4 participants