How to Use Experimental Exclude Patterns in osv-scanner Scans
Use the --experimental-exclude flag with osv-scanner scan source to skip directories using exact matches, glob patterns (prefix with g:), or regular expressions (prefix with r:).
The osv-scanner tool from Google provides an experimental mechanism to filter directories during vulnerability scans. This feature parses exclusion rules from the command line, compiles them into optimized matchers, and injects them into the underlying Scalibr scanning engine. Understanding how these experimental exclude patterns are processed helps you optimize scan times by eliminating irrelevant paths like test suites or dependency caches.
How the Experimental Exclude Flag Works
The implementation spans multiple packages, converting CLI arguments into compiled patterns that the file system walker uses to prune directories.
CLI Flag Definition
The flag is declared in cmd/osv-scanner/scan/source/command.go as a StringSliceFlag, allowing multiple exclusion rules in a single scan:
&cli.StringSliceFlag{
Name: "experimental-exclude",
Usage: "exclude directory paths during scanning; use g:pattern for glob, r:pattern for regex, or just dirname for exact match (can be repeated)",
},
The parsed values are stored in experimentalScannerActions.ExcludePatterns before being passed to the scanning logic.
Pattern Parsing and Compilation
In pkg/osvscanner/exclude.go, the parseExcludePatterns function processes each argument. It uses parseExcludeArg to split entries into a type prefix and raw pattern:
- Exact match – no prefix (stored in
dirsToSkip) - Glob –
g:prefix (compiled usinggithub.com/gobwas/glob) - Regex –
r:prefix (compiled into a cachedregexp.Regexp)
The compiled results are held in the excludePatterns struct:
type excludePatterns struct {
dirsToSkip []string
globPattern glob.Glob
regexPattern *regexp.Regexp
}
Glob patterns are merged internally with {p1,p2,…} syntax, while regex patterns use alternation (p1|p2|…) for efficiency.
Scanner Integration
The DoScan function in pkg/osvscanner/scan.go injects these patterns into the Scalibr configuration:
DirsToSkip: excludePatterns.dirsToSkip,
SkipDirRegex: excludePatterns.regexPattern,
SkipDirGlob: excludePatterns.globPattern,
Scalibr’s directory walker checks each path against these three matchers during the file system traversal. Any match causes the walker to skip that directory and its children silently.
Pattern Syntax and Types
osv-scanner supports three distinct pattern types, differentiated by their prefix.
Exact Directory Names
Provide the directory name without any prefix to exclude specific folder names regardless of their location in the tree. These are collected in the dirsToSkip slice and matched literally against path components.
osv-scanner scan source -r \
--experimental-exclude=test \
--experimental-exclude=docs \
./my/project
Glob Patterns
Prefix the pattern with g: to use glob syntax. This supports wildcards like * (single level) and ** (recursive) to match directories at any depth.
osv-scanner scan source -r \
--experimental-exclude="g:**/vendor/**" \
./my/project
The glob compiler merges multiple patterns for efficient matching.
Regular Expressions
Prefix with r: to supply a RE2-compatible regular expression. This is useful for complex exclusion rules, such as matching directories ending with specific suffixes.
osv-scanner scan source -r \
--experimental-exclude="r:\\.cache$" \
./my/project
Malformed regex patterns return an error during the compilation phase.
Command Line Examples
You can combine multiple pattern types in a single scan by repeating the flag:
# Mixed exclusion: exact name, glob, and regex
osv-scanner scan source -r \
--experimental-exclude=nested \
--experimental-exclude="g:**/test/**" \
--experimental-exclude="r:^tmp_" \
./my/project
All exclusions are documented in docs/scan-source.md along with usage notes.
Programmatic Usage
When integrating osv-scanner into Go applications, populate the ExperimentalScannerActions struct:
package main
import (
"github.com/google/osv-scanner/v2/pkg/osvscanner"
"github.com/google/osv-scanner/v2/internal/helper"
)
func main() {
exp := osvscanner.ExperimentalScannerActions{
ExcludePatterns: []string{
"vendor", // exact match
"g:**/test/**", // glob
"r:\\.cache$", // regex
},
}
scan := helper.CommonScannerActions{
Recursive: true,
DirectoryPaths: []string{"./my/project"},
ExperimentalScannerActions: exp,
}
results, err := osvscanner.DoScan(scan)
if err != nil && err != osvscanner.ErrNoPackagesFound {
panic(err)
}
// Process results...
}
The ExcludePatterns slice flows through the same parsing pipeline used by the CLI, as defined in pkg/osvscanner/exclude.go.
Summary
- The
--experimental-excludeflag enables directory filtering duringosv-scanner scan sourceoperations. - Patterns support three modes: exact names (no prefix), globs (
g:prefix), and regexes (r:prefix). - Implementation resides in
cmd/osv-scanner/scan/source/command.go(CLI),pkg/osvscanner/exclude.go(parsing), andpkg/osvscanner/scan.go(injection). - Glob patterns use the
github.com/gobwas/globlibrary; regex patterns use Go’s standardregexppackage. - The feature is experimental and tested in
cmd/osv-scanner/scan/source/command_test.go.
Frequently Asked Questions
Is the exclude pattern feature stable?
No, this is an experimental feature. The --experimental-exclude flag name, syntax, and behavior may change in future releases of osv-scanner as the implementation matures. Monitor the project’s changelog for updates.
Can I use multiple exclude patterns in one command?
Yes. The flag accepts multiple values. You can repeat --experimental-exclude with different patterns, mixing exact names, globs, and regexes in the same scan invocation. The scanner applies all patterns cumulatively.
What regex engine does osv-scanner use?
The tool uses Go’s standard regexp package (RE2 syntax) for regex patterns. Patterns prefixed with r: must be valid RE2 expressions; otherwise, parseExcludePatterns returns a compilation error before scanning begins.
How do I exclude directories nested at any depth?
Use a glob pattern with the ** wildcard. Prefix your pattern with g: and use syntax like **/vendor/** to match and exclude vendor directories regardless of their depth in the project hierarchy.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →