Gatecheck
Gatecheck

Gatecheck automates report validation in a CI/CD Pipeline by comparing security findings to pre-determined thresholds. It also provides report aggregation, artifact integrity, and deployment validation. Gatecheck is stateless so self-hosting and provisioning servers is not required.

Getting Started
The fastest way to get started with Gatecheck is to download the pre-built binaries for your target system.
cd <target install dir>
curl -L <OS Specific Release>.tar.gz | tar xz
./gatecheck --help
The Gatecheck CLI supports --help for every command.
Update a release binary in place. --check only prints the current and latest versions.
gatecheck update --check
gatecheck update
Generate a configuration file with the default thresholds. Every rule starts disabled, and coverage thresholds start at 0.
gatecheck config init > gatecheck.yaml
Validate a report. The config is a flag. The report type comes from the file contents. The filename is used when the contents are ambiguous, so a Grype report can still be named grype-report.json.
gatecheck validate --config gatecheck.yaml grype-report.json
gatecheck agent-guide (alias llm) prints a markdown guide for coding agents. The same text is docs/agent-guide.md.
gatecheck bootstrap installs pinned Grype, Syft, Gitleaks, semgrep’s experimental osemgrep CLI, Trivy, and osv-scanner. gatecheck grype, gatecheck syft, gatecheck gitleaks, gatecheck semgrep, gatecheck osemgrep, gatecheck trivy, and gatecheck osv-scanner run them.
Summarize Reports with List
gatecheck ls --help
List with EPSS scores is supported for Grype, CycloneDX, Trivy, and osv-scanner reports.

Validation
gatecheck validate --help

Bundling Artifacts
Bundling artifacts produces a gzipped tarball and a manifest. list and validate recognize a bundle from that manifest. A name that contains bundle still works when the contents are ambiguous.
gatecheck bundle create gatecheck-bundle.tar.gz grype-report.json

Installation
Prerequisites
Before installing Gatecheck, make sure your system meets the following requirements:
- Operating System: Windows, macOS, or Linux.
- Go: Version 1.26.0 or newer (only required if you plan to build the application from source).
Installation Options
Gatecheck can be installed either by downloading the pre-compiled binary for your operating system or by compiling the source code.
Option 1: Installing from Binary
-
Download the Binary: Visit the Gatecheck GitHub releases page at
https://github.com/gatecheckdev/gatecheck/releasesand download the latest version for your operating system. -
Unpack the Binary (if necessary): For Windows and Linux, you may need to unpack the
.zipor.tar.gzfile. -
Move the Binary to a Bin Directory:
- Windows: Move
gatecheck.exeto a directory within your PATH, such asC:\Windows. - macOS/Linux: Move
gatecheckto a location in your PATH, such as/usr/local/bin. You can use the commandmv gatecheck /usr/local/binin the terminal.
- Windows: Move
-
Verify Installation: Open a terminal or command prompt and type
gatecheck versionorgatecheck --versionto ensure the application is installed correctly.
Option 2: Building from Source
-
Clone the Repository: Clone the Gatecheck repository to your local machine using Git:
git clone https://github.com/gatecheckdev/gatecheck -
Navigate to the Repository Directory:
cd gatecheck -
Install Task: Ensure you have Task installed.
-
Build and Install: Run:
task build task installtask buildwrites./bin/gatecheck.task installcopies that binary toINSTALL_DIR, which defaults to/usr/local/bin, and asks before it copies.To build without Task:
go build -ldflags="-X 'main.cliVersion=$(git describe --tags)' -X 'main.gitCommit=$(git rev-parse HEAD)' -X 'main.buildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ)' -X 'main.gitDescription=$(git log -1 --pretty=%B)'" -o ./bin/gatecheck ./cmd/gatecheck -
Verify Installation: Check the application version to confirm successful installation:
gatecheck version
Post-Installation Steps
After installing Gatecheck, you can begin using it by typing gatecheck followed by the necessary commands and
options in your terminal or command prompt. For a list of available commands and their descriptions, use:
gatecheck --help
Install scanners
After gatecheck itself is installed, gatecheck bootstrap downloads pinned releases of Grype, Syft, Gitleaks, Trivy, and osv-scanner, and installs semgrep’s experimental native CLI as osemgrep. The files live under the gatecheck data directory (GATECHECK_HOME, or the platform default described in Bootstrap).
gatecheck bootstrap
gatecheck grype --help
Troubleshooting
If you encounter any issues during the installation process, ensure that you have the correct permissions to install software on your system and that your Go environment is properly configured. For further assistance, please visit the Gatecheck GitHub issues page or contact support.
For more information on using Gatecheck, refer to the user documentation or the GitHub repository for examples and advanced usage.
Usage
Gatecheck is a lightweight CLI for security reports. It summarizes a report, checks it against a config, downloads EPSS and KEV data, and packs reports into one bundle.
Running gatecheck with no arguments prints nothing and exits 0. gatecheck --help lists the commands. gatecheck config, gatecheck bundle, and gatecheck download print the help for their subcommands.
Commands:
gatecheck versionprints the build information.gatecheck --versiondoes the same. The--versionflag is only on the root command.gatecheck config initprints a default config.gatecheck config convertrewrites one into another format.gatecheck list(aliaseslsandprint) prints one report.gatecheck list-allprints several.gatecheck validatecompares one report, or one bundle, to the config.gatecheck bundle create,bundle add, andbundle removemanage a bundle.gatecheck download epssandgatecheck download kevwrite the upstream data to standard output. EPSS files are cached until the published date changes.gatecheck bootstrapinstalls Grype, Syft, Gitleaks, semgrep’s experimental osemgrep CLI, Trivy, and osv-scanner.gatecheck grype,syft,gitleaks,semgrep,osemgrep,trivy, andosv-scannerrun those programs. See Bootstrap.gatecheck update(aliasesself-updateandupgrade) replaces this binary with a GitHub release after checking the archive checksum.gatecheck update --checkonly prints the current and latest versions.gatecheck agent-guide(aliasllm) prints a markdown guide for coding agents.gatecheck completionprints a shell completion script.gatecheck help [command]prints help for that command.
list and validate decide the report type from the file contents. The filename is the fallback when the contents are ambiguous. See Supported Reports.
Logs go to standard error. Tables, downloaded data, and config init go to standard output.
Exit status:
0when the command succeeds. Withvalidate --audit, an error returned by the check also exits 0.1when a report misses a configured threshold and--auditis off.255for a missing file, a rejected command line, or a check error when--auditis off.- The scanner commands return that program’s own status. A scanner that is neither installed nor on
PATHexits 255.
Validation lists which validate failures are which status.
--verbose (-v) prints debug logs. --silent hides debug, info, and warning logs, and errors are still printed. The two flags cannot be used together. They are available on every command.
Bootstrap
gatecheck bootstrap downloads the scanners whose reports gatecheck reads, checks each file, and installs them under a gatecheck data directory.
gatecheck bootstrap
gatecheck bootstrap --tools grype,syft
gatecheck bootstrap --list
Pinned versions are compiled into gatecheck. The current pins are Grype 0.121.0, Syft 1.55.0, Gitleaks 8.30.1, semgrep 1.182.1, Trivy 0.76.1, and osv-scanner 2.7.0. They live in internal/bootstrap/versions.go.
Directory
Binaries go in bin under the gatecheck home.
GATECHECK_HOME sets that directory. When it is empty, the location is:
- Linux:
$XDG_DATA_HOME/gatecheck, or~/.local/share/gatecheck. - macOS:
$XDG_DATA_HOME/gatecheckwhenXDG_DATA_HOMEis set, otherwise~/Library/Application Support/gatecheck. - Windows:
%LOCALAPPDATA%\gatecheck, then%APPDATA%\gatecheck, then the user profile.
A second run that already has the pinned file and its version stamp prints <tool> <version> already installed and skips the download. --force downloads again. The stamp is written after the binary is in place.
--list prints managed installs and does not download. --force is ignored while listing. A binary with no stamp shows unknown. A missing tool shows -.
TOOL PINNED INSTALLED PATH
grype 0.121.0 0.121.0 /home/ada/.local/share/gatecheck/bin/grype
syft 1.55.0 - -
gitleaks 8.30.1 8.30.1 /home/ada/.local/share/gatecheck/bin/gitleaks
semgrep 1.182.1 1.182.1 /home/ada/.local/share/gatecheck/bin/osemgrep
trivy 0.76.1 0.76.1 /home/ada/.local/share/gatecheck/bin/trivy
osv-scanner 2.7.0 2.7.0 /home/ada/.local/share/gatecheck/bin/osv-scanner
Flags
--tools: comma-separated names. The default isgrype,syft,gitleaks,semgrep,trivy,osv-scanner. Names are lowercased.osemgrepmeanssemgrep. An unknown name is an error:unknown tool "not-a-scanner" (supported: grype, syft, gitleaks, semgrep, trivy, osv-scanner).--force: reinstall even when the pinned version is already present.--list: print the table above.
bootstrap takes no positional arguments.
Grype, Syft, Gitleaks, and Trivy
Each tool is a GitHub release asset. gatecheck downloads <name>_<version>_checksums.txt, looks up the asset’s SHA-256, downloads the archive, and checks the digest before extracting the binary. The install is a write to a temporary file in the destination directory, then a rename.
| Tool | Release | Asset name |
|---|---|---|
| Grype | anchore/grype | grype_<version>_<os>_<arch>.tar.gz, or .zip on Windows |
| Syft | anchore/syft | syft_<version>_<os>_<arch>.tar.gz, or .zip on Windows |
| Gitleaks | gitleaks/gitleaks | gitleaks_<version>_<os>_<arch>.tar.gz, or .zip on Windows |
| Trivy | aquasecurity/trivy | trivy_<version>_<OS>-<arch>.tar.gz, or .zip on Windows |
Gitleaks names amd64 as x64, 386 as x32, and arm as armv6 or armv7.
Trivy uses its own asset names: Linux-64bit, Linux-32bit, Linux-ARM (armv7), Linux-ARM64, Linux-PPC64LE, Linux-s390x, macOS-64bit, macOS-ARM64, windows-64bit, and FreeBSD-64bit. The checksum file is trivy_<version>_checksums.txt. The archive contains trivy, or trivy.exe on Windows, plus README.md, LICENSE, and template files. gatecheck installs only the binary.
Published assets:
- Grype: macOS amd64 and arm64; Linux amd64, arm64, ppc64le, and s390x; Windows amd64.
- Syft: macOS amd64 and arm64; Linux amd64, arm64, ppc64le, riscv64, and s390x; Windows amd64 and arm64.
- Gitleaks: macOS x64 and arm64; Linux x64, x32, arm64, armv6, and armv7; Windows x64, x32, and arm64.
- Trivy: macOS amd64 and arm64; Linux 386, amd64, armv7, arm64, ppc64le, and s390x; Windows amd64; FreeBSD amd64.
A platform with no asset fails that tool. The message looks like grype has no published release asset for windows/arm64. Other requested tools still install. The command exits 255 when any requested tool failed this way, or when a download or checksum check failed.
osv-scanner
osv-scanner publishes a raw binary, not an archive. gatecheck downloads osv-scanner_SHA256SUMS from the google/osv-scanner release, checks the asset’s SHA-256, marks the file executable, and installs it as osv-scanner, or osv-scanner.exe on Windows.
Asset names:
osv-scanner_linux_amd64andosv-scanner_linux_arm64osv-scanner_darwin_amd64andosv-scanner_darwin_arm64osv-scanner_windows_amd64.exeandosv-scanner_windows_arm64.exe
Those six platforms are the published set. Anything else fails that tool with the same kind of message as a missing Grype asset.
Semgrep (osemgrep)
Semgrep publishes no GitHub release assets. Bootstrap reads https://pypi.org/pypi/semgrep/<version>/json, picks the wheel for this machine, and checks the wheel against the SHA-256 in that JSON.
The wheel contains a native binary at semgrep-<version>.data/purelib/semgrep/bin/semgrep-core, and on Linux a semgrep/bin/libs/ directory of shared libraries. Invoked with argv[0] osemgrep, that binary is semgrep’s experimental native CLI.
On macOS and Linux, gatecheck installs semgrep-core and a symlink named osemgrep in the same directory, plus libs/ beside them. On Windows it installs one copy named osemgrep.exe. Success looks like installed semgrep 1.182.1 /home/ada/.local/share/gatecheck/bin/osemgrep.
Wheels exist for:
- macOS x86_64 and arm64
- Linux glibc (
manylinux) and musl (musllinux), x86_64 and aarch64 - Windows amd64
On Linux, gatecheck reads the dynamic linker of its own executable. An interpreter path containing musl selects the musl wheel. Anything else selects the glibc wheel.
A platform with no wheel is skipped. Standard error says semgrep: no PyPI wheel for <platform>; osemgrep wheels are published for macOS (x86_64, arm64), Linux glibc and musl (x86_64, aarch64), and Windows amd64. A wheel that has no semgrep-core is also skipped: semgrep: wheel <filename> does not contain semgrep-core; skipped. A skip leaves the command successful when every other requested tool succeeded. A bad digest or a failed download is still an error.
osemgrep scan is the command that writes Semgrep JSON. gatecheck semgrep and gatecheck osemgrep add --experimental immediately after scan when you did not pass it. Other osemgrep commands need that flag from you. osemgrep --version tries to execute pysemgrep and fails. This works:
gatecheck semgrep --experimental --version
Running a scanner
gatecheck grype dir:. -o json > grype-report.json
gatecheck syft dir:. -o cyclonedx-json > cyclonedx-syft.json
gatecheck gitleaks detect --report-format json --report-path gitleaks-report.json
gatecheck semgrep scan -e 'eval($X)' -l python --json t.py > semgrep-report.json
gatecheck trivy fs --format json --output trivy-report.json .
gatecheck osv-scanner scan source --format json . > osv-scanner-report.json
Arguments, standard input, standard output, standard error, and the scanner’s exit status are passed through. gatecheck grype --help is Grype’s help. gatecheck does not parse flags after these command names.
The managed binary is used when it is present. Otherwise gatecheck looks on PATH: grype, syft, gitleaks, trivy, or osv-scanner for those commands; semgrep and then osemgrep for gatecheck semgrep; osemgrep only for gatecheck osemgrep. --experimental is inserted only when the program that will run is named osemgrep. A Python semgrep on PATH is left unchanged.
When neither copy exists, the command prints one line and exits 255:
gatecheck: grype is not installed; run `gatecheck bootstrap`
The name in that line is the command you typed.
What stays outside bootstrap
Coverage files (LCOV, Clover, Cobertura) come from the language toolchain. Bootstrap does not install those tools.
CycloneDX is a report format. Syft writes it with -o cyclonedx-json, and Grype can write a CycloneDX vulnerability report. Those are the files list and validate score. Any other tool’s CycloneDX JSON BOM is scored the same way. There is no separate CycloneDX scanner.
Syft’s own JSON is still rejected. list and validate return an error for that document. A filename that contains syft does the same when the contents are ambiguous. Syft is installed so it can write CycloneDX.
Trivy JSON (trivy fs --format json, trivy image --format json, and the other Trivy scanners’ JSON output) is a report type. The contents identify it. A filename containing trivy is the fallback when the contents are ambiguous. A CycloneDX BOM stays CycloneDX even when the name contains trivy. Misconfigurations, secrets, and licenses are ignored. Trivy SARIF is a SARIF report.
osv-scanner JSON (osv-scanner scan source --format json) is a report type. The contents identify it when results holds objects with a packages array. A filename containing osv is the fallback, so osv-scanner-report.json still works when the document is only {"results":[]}. Each vulnerability group is one finding. Aliases of that group are not counted again. max_severity is a CVSS base score. License-only packages are skipped.
CLI Reference
Global flags, accepted on every command:
-v,--verbose: print debug logs.--silent: hide debug, info, and warning logs. Errors are still printed.-h,--help: help for that command.
--verbose and --silent cannot be set together.
When a setting has both a flag and an environment variable, a non-empty flag wins. An empty flag falls through to the environment variable, then to the default.
gatecheck
gatecheck [flags]
gatecheck [command]
With no arguments, the command prints nothing and exits 0.
--version: print the same build information asgatecheck version. This flag is only on the root command.
gatecheck version
gatecheck version
Prints the logo and the build information: CLI version, git commit, build date, git description, platform, Go version, and compiler. A build that does not pass those values prints [Not Provided].
gatecheck config init
gatecheck config init
Prints a default config to standard output. Every rule is disabled and every coverage threshold is 0.
-o,--output:json,.json,toml,.toml,yaml,yml,.yaml, or.yml. The default isyaml. Any other value is an error. The match is case sensitive.
gatecheck config init > gatecheck.yaml
gatecheck config init --output json > gatecheck.json
gatecheck config convert
gatecheck config convert
Reads a config file and prints it in another format.
-f,--file: file to read. The default isgatecheck.yaml. The extension picks the decoder (.yaml,.yml,.json,.toml).-o,--output: format to write. Same accepted values asconfig init. The default isyaml.
gatecheck config convert --file gatecheck.yaml --output toml
gatecheck list
gatecheck list [FILE]
Aliases: ls, print.
Prints a table for one report. The first filename is the one that is opened. Further filenames are ignored. Use list-all for more than one file. A Grype, CycloneDX, SARIF, Semgrep, Gitleaks, Trivy, or osv-scanner report with no findings prints one sentence and no table: No grype vulnerabilities, No cyclonedx vulnerabilities, No sarif findings, No semgrep findings, No gitleaks findings, No trivy vulnerabilities, or No osv-scanner vulnerabilities. --markdown prints that same sentence.
The report type comes from the file contents. See Supported Reports.
With no filename, the command reads standard input and --input-type is required.
-i,--input-type: type word used when reading standard input and the contents are ambiguous. It is matched with the same rules as a filename.grype,cyclonedx,sarif,semgrep,gitleaks,trivy,osv,syft,bundle, and the coverage words all work. Clear contents win over this flag. See Supported Reports.--markdown: print a markdown table.--epss: add EPSS score and percentile columns. This changes the table for Grype, CycloneDX, Trivy, and osv-scanner. Other report types still list, and the EPSS data is not shown. With no local file, gatecheck downloads the current EPSS CSV and caches it until the published date changes. Requests send a User-Agent with the gatecheck version and project URL.--epss-filename: read that CSV instead of calling the API.GATECHECK_EPSS_FILENAMEis the same setting.--epss-url: EPSS API URL. An empty value useshttps://epss.cyentia.com.GATECHECK_EPSS_URLis the same setting.--epss-cache-dir: cache directory for that download.GATECHECK_EPSS_CACHE_DIRis the same setting.--epss-no-cache: download on every run.GATECHECK_EPSS_CACHE=offdoes the same.
gatecheck list grype-report.json
gatecheck list --markdown --epss grype-report.json
grype bkimminich/juice-shop:latest -o json | gatecheck ls --input-type grype
gatecheck list-all
gatecheck list-all [FILE...]
Prints each filename, then its table, or one sentence when that report has no findings. A file whose contents and name are not a supported list-all type is skipped with a warning. Coverage files are in that skipped set. A missing file is skipped. A list error is logged and the command continues. The command exits 0 after the last file.
--markdown: print markdown tables.--epss: download EPSS data and add it for Grype, CycloneDX, Trivy, and osv-scanner reports. The type comes from the file contents, then the filename. The download happens per file and is cached until the published date changes. There is no--epss-filenameflag.GATECHECK_EPSS_URLoverrides the API.GATECHECK_EPSS_FILENAMEis not read by this command. Requests send a User-Agent with the gatecheck version and project URL.--epss-cache-dir: cache directory for that download.GATECHECK_EPSS_CACHE_DIRis the same setting.--epss-no-cache: download on every run.GATECHECK_EPSS_CACHE=offdoes the same.
gatecheck validate
gatecheck validate [FILE]
FILE is required. The config is a flag.
-f,--config: config file.GATECHECK_CONFIG_FILENAMEis the same setting. With neither, the built-in default config is used (every rule disabled, coverage thresholds0).--epss-filename: EPSS CSV to use when an EPSS rule is enabled.GATECHECK_EPSS_FILENAMEis the same setting.--epss-cache-dir: cache directory used when that CSV is downloaded.GATECHECK_EPSS_CACHE_DIRis the same setting.--epss-no-cache: download on every run.GATECHECK_EPSS_CACHE=offdoes the same.--kev-filename: CISA KEV JSON to use when a KEV rule is enabled.-a,--audit: print the error from the check and exit 0. A missing report, a missing config, or a bad flag still exits 255.
validate has no --epss-url or --kev-url flag. GATECHECK_EPSS_URL and GATECHECK_KEV_URL still override those APIs when the matching file flag is empty. The defaults are the same URLs download uses.
EPSS data is loaded only when an EPSS limit or EPSS risk acceptance rule is enabled. When --epss-filename is not set, gatecheck downloads the current EPSS file and caches it until the published date changes. Requests send a User-Agent with the gatecheck version and project URL.
KEV data is loaded only when kevLimitEnabled is true for Grype or CycloneDX.
gatecheck validate --config gatecheck.yaml grype-report.json
gatecheck validate --audit --config gatecheck.yaml gatecheck-bundle.tar.gz
See Validation for rule order and exit codes.
gatecheck bundle create
gatecheck bundle create BUNDLE_FILE TARGET_FILE
Alias: init.
Creates a bundle and stores the target file in it. The label is the base name of the target file (reports/grype-report.json is stored as grype-report.json).
-t,--tag: tag stored on that file. Repeat the flag for more than one tag.GATECHECK_BUNDLE_TAGis a comma-separated list used when no tag flag is passed.
gatecheck bundle create gatecheck-bundle.tar.gz grype-report.json --tag ci
gatecheck bundle add
gatecheck bundle add BUNDLE_FILE TARGET_FILE
Adds another file to an existing bundle. The label is the base name of the target file. --tag and GATECHECK_BUNDLE_TAG work the same way as on bundle create.
gatecheck bundle remove
gatecheck bundle remove BUNDLE_FILE LABEL
Alias: rm.
Deletes the file with that label. The label is the base name used when the file was added, not a path that is opened. A label that is not in the bundle is logged and the command still exits 0.
gatecheck download epss
gatecheck download epss
Writes the FIRST.org EPSS CSV to standard output.
EPSS scores are cached in the user cache directory, under gatecheck/epss. gatecheck checks the redirect to the dated filename and downloads the CSV only when that file is not already cached. Requests send a User-Agent with the gatecheck version and project URL.
--epss-url: API URL. An empty value useshttps://epss.cyentia.com.GATECHECK_EPSS_URLis the same setting.--epss-cache-dir: cache directory.GATECHECK_EPSS_CACHE_DIRis the same setting.--epss-no-cache: download on every run.GATECHECK_EPSS_CACHE=offdoes the same.
gatecheck download epss > epss.csv
gatecheck download kev
gatecheck download kev
Writes the CISA Known Exploited Vulnerabilities catalog as JSON to standard output.
--kev-url: API URL. An empty value useshttps://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json.GATECHECK_KEV_URLis the same setting.
gatecheck download kev > kev.json
gatecheck bootstrap
gatecheck bootstrap
Downloads Grype, Syft, Gitleaks, semgrep’s experimental osemgrep CLI, Trivy, and osv-scanner into the gatecheck data directory. Each GitHub asset is checked against the project’s SHA-256 checksum file. The semgrep wheel is checked against the digest in the PyPI JSON. A tool already at the pinned version is skipped. See Bootstrap.
--tools: comma-separated scanners. Defaultgrype,syft,gitleaks,semgrep,trivy,osv-scanner.osemgrepselects semgrep.--force: download again when the pinned version is already installed.--list: print pinned version, installed version, and path. This does not download.
GATECHECK_HOME is the data directory. Binaries are in its bin subdirectory.
gatecheck bootstrap
gatecheck bootstrap --list
gatecheck grype, syft, gitleaks, semgrep, osemgrep, trivy, osv-scanner
gatecheck grype [scanner arguments]
gatecheck syft [scanner arguments]
gatecheck gitleaks [scanner arguments]
gatecheck semgrep [scanner arguments]
gatecheck osemgrep [scanner arguments]
gatecheck trivy [scanner arguments]
gatecheck osv-scanner [scanner arguments]
Runs the managed binary. Arguments and streams are passed through, and the process exits with the scanner’s status. Flags after the command name are not parsed by gatecheck, so gatecheck grype --help is Grype’s help.
The managed copy is preferred. If it is absent, the same tool name on PATH is used. gatecheck semgrep also accepts osemgrep on PATH. gatecheck osemgrep looks only for osemgrep.
semgrep and osemgrep run the osemgrep binary from the semgrep wheel. For scan, --experimental is added when you omitted it and the program that will run is named osemgrep. Other osemgrep commands need you to pass --experimental. gatecheck semgrep --experimental --version prints the osemgrep version.
If no binary is found, the command prints gatecheck: <name> is not installed; run gatecheck bootstrap`` and exits 255.
gatecheck agent-guide
gatecheck agent-guide
Alias: llm.
Prints a markdown guide for agents that run the CLI. The text is docs/agent-guide.md.
gatecheck agent-guide
gatecheck llm
gatecheck update
gatecheck update
Aliases: self-update, upgrade.
Replaces the running gatecheck binary with a release from https://github.com/gatecheckdev/gatecheck/releases. The running version is main.cliVersion, which goreleaser sets with ldflags. The default is the latest release.
Release archives are named gatecheck_<version>_<os>_<arch>.tar.gz for darwin, linux, and windows. The version in the name has no leading v. Windows archives are tar.gz, the same as the other operating systems. gatecheck downloads checksums.txt and checks the SHA256 before it replaces the binary. A missing or different checksum stops the update.
The new file is written next to the resolved executable (os.Executable, then filepath.EvalSymlinks) and renamed into place. On Windows the running executable is renamed aside first, because a running .exe cannot be overwritten. If that directory is not writable, the command stops and tells you to re-run with sudo or to reinstall into a directory you can write.
A build whose version is unset, dev, [Not Provided], or otherwise not a release version does not update unless --version is set.
--check: print the current version and the latest release, then exit 0. The archive is not downloaded.--version vX.Y.Z: install that release instead of the latest. With--check, print that release as the target and do not download.-y,--yes: do not ask for confirmation.
When stdin is a terminal and --yes is not set, gatecheck asks before replacing the binary. When stdin is not a terminal, the update runs only with --yes.
GITHUB_TOKEN, when set, is sent on the GitHub requests. The client uses the default transport, so the proxy environment variables apply. Requests use the same gatecheck User-Agent as EPSS downloads. No other command contacts GitHub for updates.
gatecheck update --check
gatecheck update
gatecheck update --version v0.8.1 --yes
gatecheck completion
gatecheck completion bash
gatecheck completion fish
gatecheck completion powershell
gatecheck completion zsh
Prints a completion script for that shell.
gatecheck help
gatecheck help [command]
Prints help for a command. gatecheck validate --help does the same.
Environment variables
| Variable | Commands | Same as |
|---|---|---|
GATECHECK_CONFIG_FILENAME | validate | --config |
GATECHECK_EPSS_FILENAME | list, validate | --epss-filename |
GATECHECK_EPSS_URL | download epss, list, list-all, validate | --epss-url on download epss and list |
GATECHECK_EPSS_CACHE_DIR | download epss, list, list-all, validate | --epss-cache-dir |
GATECHECK_EPSS_CACHE | download epss, list, list-all, validate | --epss-no-cache when the value is off |
GATECHECK_KEV_URL | download kev, validate | --kev-url on download kev |
GATECHECK_BUNDLE_TAG | bundle create, bundle add | --tag, as a comma-separated list |
GATECHECK_HOME | bootstrap, grype, syft, gitleaks, semgrep, osemgrep, trivy, osv-scanner | data directory; binaries are in bin under it |
List Reports
Most scanning tools can print their own table. Grype is one example:
grype bkimminich/juice-shop:latest -o table

Gatecheck prints a shorter table from the JSON those tools already emit. Pipe the JSON in, or point the command at a file.
grype bkimminich/juice-shop:latest -o json | gatecheck ls --input-type grype
gatecheck ls grype-scan-report.json

The report type comes from the file contents. The filename, or --input-type on standard input, is used when the contents are ambiguous. grype-scan-report.json still works. See Supported Reports.
--markdown prints a markdown table instead of the plain text table.
--epss adds the EPSS score and percentile for Grype, CycloneDX, Trivy, and osv-scanner. Other reports ignore that data. With no --epss-filename, gatecheck downloads the CSV from FIRST. GATECHECK_EPSS_FILENAME and GATECHECK_EPSS_URL are the same settings as those flags.
gatecheck download epss > epss.csv
gatecheck list --epss --epss-filename epss.csv grype-scan-report.json
Columns:
- Grype: severity, package, version, link. With
--epss: CVE id, severity, EPSS score, EPSS percentile, package, version, link. - CycloneDX: CVE id, severity, package, link. With
--epss: CVE id, severity, EPSS score, EPSS percentile, affected packages, link. - Semgrep: check id, OWASP ids, severity, impact, link. Runtime errors from the report are logged as warnings.
- Gitleaks: rule id, file, commit, start line.
- SARIF: rule id, severity, location, tool. A result that passed, is suppressed, or has level
noneis left out. - Trivy: severity, package, version, link. With
--epss: CVE id, severity, EPSS score, EPSS percentile, package, version, link. Misconfigurations are omitted. - osv-scanner: severity, package, version, link. With
--epss: id, severity, EPSS score, EPSS percentile, package, version, link. The id is the first CVE alias, or the OSV id when there is no CVE. Groups are listed once. - Coverage: lines, functions, and branches covered, with a percent in the footer. The percent is only for display. The config file uses a ratio. See Configuration.
- Bundle: label, SHA-256 digest, tags, size.
A Grype, CycloneDX, SARIF, Semgrep, Gitleaks, Trivy, or osv-scanner report with no findings prints one sentence and no table. The lines are No grype vulnerabilities, No cyclonedx vulnerabilities, No sarif findings, No semgrep findings, No gitleaks findings, No trivy vulnerabilities, and No osv-scanner vulnerabilities. --markdown prints that same line.
list opens the first filename only. list-all walks every filename, prints the name, then the table or that sentence, and skips files it does not support. Coverage files are in that skipped set. --epss on list-all adds EPSS columns for Grype, CycloneDX, Trivy, and osv-scanner, including a file whose name does not contain those words when the contents do. It always uses the API (GATECHECK_EPSS_URL to override it).
gatecheck list-all grype-scan-report.json semgrep-report.json
Gatecheck Bundle
A bundle is a gzipped tar with a JSON manifest. It holds the report bytes, a SHA-256 digest, and any tags you set. The suggested name is gatecheck-bundle.tar.gz. list and validate treat a file as a bundle when the gzipped tar contains gatecheck-manifest.json. When the contents are ambiguous, validate still requires bundle in the name, and list also accepts gatecheck.
Create
gatecheck bundle create gatecheck-bundle.tar.gz grype-report.json --tag ci
bundle init is the same command. The label stored in the manifest is the base name of the target file. validate reads each stored file’s contents to pick the type, and uses the label only when the contents are ambiguous. A CycloneDX, Trivy, or osv-scanner file is still validated as that type when the stored name would suggest something else.
Repeat --tag for more than one tag. When the flag is omitted, GATECHECK_BUNDLE_TAG is read as a comma-separated list.
Add
gatecheck bundle add gatecheck-bundle.tar.gz semgrep-report.json
gatecheck bundle add gatecheck-bundle.tar.gz gitleaks-report.json --tag audit
The bundle file has to exist already.
Remove
gatecheck bundle remove gatecheck-bundle.tar.gz semgrep-report.json
bundle rm is the same command. The second argument is the label. A label that is not in the bundle is logged, and the command exits 0.
Inspect
There is no bundle list subcommand. List the manifest with list:
gatecheck list gatecheck-bundle.tar.gz
The table columns are label, digest, tags, and size.
Validate
gatecheck validate --config gatecheck.yaml gatecheck-bundle.tar.gz
Each stored file is checked on its own with the same rules as a standalone file. Files that do not match a supported type are skipped, including Syft JSON. A Grype failure and a Semgrep failure in the same bundle are both reported, and the command exits 1.
Validation
gatecheck validate --config gatecheck.yaml grype-report.json
gatecheck validate --config gatecheck.yaml gatecheck-bundle.tar.gz
Pass the config with --config or -f, or with GATECHECK_CONFIG_FILENAME. The only positional argument is the report path, and it is required.
The report type comes from the file contents, and from the filename when the contents are ambiguous. See Supported Reports.
With no config, gatecheck uses the default: every rule disabled, coverage thresholds 0. Grype, CycloneDX, Trivy, osv-scanner, SARIF, Semgrep, Gitleaks, coverage, and bundle reports pass under that default. Syft JSON still returns an error. An old config with no sarif section leaves those limits disabled.
Exit status
0: the report passed.1: a threshold failed. The error text starts withvalidation failure:.255: the report or config could not be opened, the config extension is not supported, or the command line was rejected.
--audit (-a) prints whatever error the check returns and exits 0. That covers a failed threshold, an unknown report, a Syft file, a decode error, and a failed EPSS or KEV fetch. Opening the report, the config, and any --epss-filename or --kev-filename happens before the check. A missing file still exits 255.
Grype, CycloneDX, Trivy, and osv-scanner
Trivy uses these same rules. It counts vulnerability entries from Results[].Vulnerabilities. Misconfigurations, secrets, and licenses are not scored. An id matches VulnerabilityID or a VendorIDs entry, without regard to case. EPSS and KEV look up the first id that starts with CVE-.
osv-scanner uses these same rules. It counts one finding per vulnerability group, so aliases are not double-counted. License-only packages are skipped. max_severity is a CVSS base score (9.8 is critical, 7.5 is high, 4.0 is medium, 0.1 is low). The words CRITICAL, HIGH, MEDIUM, LOW, MODERATE, and UNKNOWN are accepted, and MODERATE maps to medium. A CVSS vector with no numeric score is unknown unless database_specific.severity supplies a rating. Deny, allow, and KEV match the OSV id or any alias. EPSS and KEV look up the first id that starts with CVE-.
Rules run in this order. A failure returns immediately, except where a rule only removes findings.
- CVE limit.
cveLimit, when enabled, fails if any listed id is in the report. Ids are compared without regard to case. - Disabled Grype, Trivy, and osv-scanner severities. Grype, Trivy, and osv-scanner drop findings whose severity limit is disabled. If the EPSS limit is also enabled, a finding at a disabled severity stays in the report when it has an EPSS score greater than or equal to that limit. CycloneDX leaves findings at a disabled severity in the report, so they still go through the KEV and EPSS rules.
- CVE risk acceptance. Matching ids are removed and skip the remaining rules.
- KEV limit. When
kevLimitEnabledis true, a CVE that is in the catalog fails the report. The catalog is--kev-filenameor, with no file, the CISA feed.GATECHECK_KEV_URLoverrides the feed. There is no--kev-urlflag onvalidate. - EPSS risk acceptance. A CVE is removed when the configured
scoreis greater than that CVE’s EPSS score. A CVE with no EPSS row is kept. A CVE whose score is equal to the configured score is kept. - EPSS limit. A CVE fails when its EPSS score is greater than
score. A CVE with no EPSS row passes this rule. A score equal to the limit passes. Data comes from--epss-filenameorGATECHECK_EPSS_FILENAME, or from the API.GATECHECK_EPSS_URLoverrides the API. There is no--epss-urlflag onvalidate. - Severity limit. For each enabled severity, the report fails when the count is greater than
limit.limit: 0allows none. Counts that are equal to the limit pass. Grype, CycloneDX, Trivy, and osv-scanner severities arecritical,high,medium, andlow.negligibleandunknownhave no limit field.
Any CycloneDX JSON BOM uses the cyclonedx rules, including a BOM from Grype, Trivy, Syft, or another tool. The severity is the highest rating. A rating with a score and no severity word uses CVSS ranges. A CVSS v2 method does not produce critical. important counts as high, and moderate counts as medium. negligible counts as none. Empty ratings use a top-level severity string when the producer set one, otherwise unknown. unknown, none, and info are not counted by the critical, high, medium, or low limits. The id is the vulnerability id, or the bom-ref when id is empty.
EPSS scores in the config are ratios from 0 to 1.
When a rule needs EPSS scores and --epss-filename is not set, gatecheck downloads the current EPSS file and caches it until the published date changes. Requests send a User-Agent with the gatecheck version and project URL.
Semgrep
- Findings whose severity limit is disabled are dropped.
- Impact risk acceptance. When enabled, a finding is removed when its impact is
high,medium, orlowand that level’s boolean is true. The three booleans are independent. - Severity limit. Severities are
error,warning, andinfo. The report fails when an enabled severity has more findings than itslimit.
SARIF
Rules run in this order. A failure returns immediately, except where a rule only removes findings.
- Rule limit.
ruleLimit, when enabled, fails if any listed rule id is in the report. Ids are compared without regard to case. This runs before disabled severities are dropped, so a denied rule fails even when its severity limit is disabled. - Disabled severities. Findings whose severity limit is disabled are dropped.
nonehas no limit field and stays in the report, but the severity rule does not count it. - Rule risk acceptance. Matching rule ids are removed and skip the remaining rules.
- Severity limit. For each enabled severity, the report fails when the count is greater than
limit.limit: 0allows none. Counts that are equal to the limit pass. Severities arecritical,high,medium, andlow.
The severity mapping is in Configuration. These results are not counted: kind of pass or notApplicable, level of none, a non-empty suppressions array, and baselineState of absent.
SARIF has no EPSS or KEV rules. A SARIF version other than 2.1.0 returns an error.
Gitleaks
When limitEnabled is true, any finding in the report fails validation. There is no numeric limit and no separate allow list.
Coverage
Line, function, and branch coverage are each covered / total. The config thresholds are those ratios, from 0 to 1. The check fails when the report’s ratio is less than the threshold. A ratio equal to the threshold passes. All three checks run, and each failure is reported. A report with no records of a kind, such as LCOV without branch records, has no ratio for it. list prints N/A, and validate skips that threshold with a warning.
0.8 means 80 percent. 80.0 fails a normal report, because 0.8 < 80.
list prints coverage as a percent. The config value stays a ratio.
Bundles
A bundle is validated when its contents are a Gatecheck bundle, or when the filename contains bundle and the contents do not identify another type. Each stored file is validated with the rules above. The file contents pick the type, and the label is the fallback. Labels that still do not match are skipped, including Syft JSON. Failures are combined, and the command exits 1 if any label fails a threshold.
Examples
Config and one report
gatecheck config init > gatecheck.yaml
gatecheck validate --config gatecheck.yaml grype-report.json
The file from config init has every rule disabled, so this passes until you turn a rule on. For 80 percent line coverage, set coverage.lineThreshold to 0.8.
EPSS from a local file
gatecheck download epss > epss.csv
gatecheck list --epss --epss-filename epss.csv grype-report.json
Bundle
The bundle name contains bundle. Each report’s contents identify its type. The base name becomes the label inside the bundle and is used only when the contents are ambiguous.
gatecheck bundle create gatecheck-bundle.tar.gz grype-report.json --tag ci
gatecheck bundle add gatecheck-bundle.tar.gz semgrep-report.json
gatecheck bundle add gatecheck-bundle.tar.gz gitleaks-report.json
gatecheck list gatecheck-bundle.tar.gz
gatecheck validate --config gatecheck.yaml gatecheck-bundle.tar.gz
Audit
gatecheck validate --audit --config gatecheck.yaml grype-report.json
A threshold failure is printed and the process exits 0. A missing report still exits 255.
Bootstrap a scanner
gatecheck bootstrap --tools grype,semgrep
gatecheck grype dir:. -o json > grype-report.json
gatecheck semgrep scan -e 'eval($X)' -l python --json t.py > semgrep-report.json
gatecheck validate --config gatecheck.yaml grype-report.json
gatecheck validate --config gatecheck.yaml semgrep-report.json
gatecheck bootstrap --tools trivy
gatecheck trivy fs --format json --output trivy-report.json .
gatecheck validate --config gatecheck.yaml trivy-report.json
gatecheck bootstrap --tools osv-scanner
gatecheck osv-scanner scan source --format json . > osv-scanner-report.json
gatecheck validate --config gatecheck.yaml osv-scanner-report.json
gatecheck semgrep scan adds --experimental when you omit it. That flag selects semgrep’s experimental native CLI, osemgrep, which writes the same Semgrep JSON list and validate already accept. gatecheck semgrep --experimental --version prints the osemgrep version.
Standard input
grype bkimminich/juice-shop:latest -o json | gatecheck list --input-type grype
Several files
gatecheck list-all grype-report.json cyclonedx-report.json semgrep-report.json
list-all skips a coverage file such as lcov.info. List that file with gatecheck list lcov.info.
Supported Reports
list and validate pick a report type from the file contents. The filename is used only when the contents do not identify a type.
Content rules, in this order:
- A gzipped tar that contains
gatecheck-manifest.jsonis a Gatecheck bundle. bomFormatofCycloneDXis CycloneDX JSON. This wins when the name containsgrype,syft,trivy, orosv, and it wins when the tool that wrote the BOM was Grype, Syft, Trivy, or another tool.- SARIF 2.1.0. The top-level
versionis the string2.1.0andrunsis an array. A$schemathat mentions SARIF is enough whenrunsis missing or null. - Grype JSON.
descriptor.nameisgrype, ormatchesis a non-empty array of objects withvulnerabilityandartifact. - Syft JSON.
descriptor.nameissyft, orschema.urlpoints at the Syft schema.listandvalidatethen return an error. Syft JSON is not implemented. A Syft CycloneDX BOM is CycloneDX, not Syft. - Semgrep JSON.
resultsis an array of objects withcheck_id, orresultsanderrorsare both arrays. Semgrep’s SARIF output is SARIF, not this type. - Gitleaks JSON. A non-empty array of objects with
RuleIDand one ofFile,Commit, orFingerprint. - Trivy JSON (
--format json).SchemaVersionis a number, andArtifactTypeis set orResultsis an array. Vulnerability entries are listed and validated. Misconfigurations, secrets, and licenses in the same file are ignored. - osv-scanner JSON (
osv-scanner scan source --format json).resultsis a non-empty array of objects with apackagesarray. One finding per vulnerability group. Aliases of that group are not counted again. License-only packages are skipped. Semgrep is checked first, so acheck_idstays Semgrep. - LCOV text. A line starts with
SF:and the file also hasDA:,LF:, orend_of_record. - Clover XML. An XML document with
clover=or a<cloverelement. - Cobertura XML. An XML document with
line-rate=.
CycloneDX XML is not read. The CycloneDX support is JSON.
When none of those match, the filename is checked. The match is a lowercase substring, and the first match wins:
grypecyclonedx. This is beforetrivy, so an ambiguous file namedcyclonedx-trivy-sbom.jsonis CycloneDX.semgrepgitleakstrivyosv.osv-scanner-report.jsonmatches.OSV-scanner.jsondoes not.syftsarifbundle.listalso accepts a name containinggatecheck.validaterequires the wordbundlefor this fallback. A real bundle is still detected from its contents when the name isproject.gcb.- Coverage, when the name contains
lcov,clover,cobertura, orcoverage, or when it ends in.info.
The filename match is case sensitive. Grype-report.json and OSV-scanner.json are not filename matches. A Grype report is still recognized from its contents when descriptor.name is grype. A Trivy or osv-scanner report is still recognized from the rules above.
An empty Grype document such as {"matches":[]} does not identify itself. The filename is what selects it. The same is true of {"results":[]} and [].
Coverage format when the name is the only signal, checked in this order:
- The name contains
lcov, or ends in.info: LCOV. - The name contains
clover: Clover XML. - The name ends in
.xml: Cobertura XML.
A name that only contains coverage, such as coverage.json, is selected as coverage and then fails, because the format is not one of those three and the contents did not identify one.
From standard input, list still requires --input-type, so the command does not wait on a terminal. The value is matched as if it were a filename called stdin:<value>, and only when the contents are ambiguous. Clear contents win over --input-type.
grype bkimminich/juice-shop:latest -o json | gatecheck list --input-type grype
list-all lists a file when the contents or the name identify Grype, Semgrep, Gitleaks, Syft, CycloneDX, SARIF, Trivy, osv-scanner, or a bundle. Coverage files are skipped with a warning. There is no --input-type flag on list-all.
Inside a bundle, validate uses the same content rules on each stored file, and falls back to the label. The label is the base name of the file you added. Labels that still do not match are skipped. Syft JSON inside a bundle is skipped.
What each command can do:
| Report | list | validate | bundle |
|---|---|---|---|
| Grype | yes | yes | yes |
| CycloneDX JSON | yes | yes | yes |
| SARIF 2.1.0 | yes | yes | yes |
| Semgrep JSON | yes | yes | yes |
| Gitleaks | yes | yes | yes |
| Trivy | yes | yes | yes |
| osv-scanner | yes | yes | yes |
| LCOV, Clover, Cobertura | yes | yes | yes |
| Syft JSON | error | error | the file is stored, and validation skips that label |
| Bundle | when the contents are a bundle, or the name contains bundle or gatecheck | when the contents are a bundle, or the name contains bundle | yes, as an ordinary file |
Configuration
validate reads YAML, JSON, or TOML. The extension selects the format: .yaml, .yml, .json, or .toml.
gatecheck config init > gatecheck.yaml
config init writes to standard output. -o / --output accepts json, .json, toml, .toml, yaml, yml, .yaml, and .yml. The default is yaml.
gatecheck config convert --file gatecheck.yaml --output json
config convert reads --file / -f (default gatecheck.yaml) and writes the other format to standard output.
A partial file is fine. Omitted fields keep the default. Keys the decoder does not know are ignored.
GATECHECK_CONFIG_FILENAME is the same setting as validate --config.
Field names below are the ones config init emits. In YAML they are case sensitive. Use the lowercase names.
Default file
This is what gatecheck config init prints.
version: "1"
metadata:
tags: []
grype:
severityLimit:
critical:
enabled: false
limit: 0
high:
enabled: false
limit: 0
medium:
enabled: false
limit: 0
low:
enabled: false
limit: 0
epssLimit:
enabled: false
score: 0
kevLimitEnabled: false
cveLimit:
enabled: false
cves: []
epssRiskAcceptance:
enabled: false
score: 0
cveRiskAcceptance:
enabled: false
cves: []
cyclonedx:
severityLimit:
critical:
enabled: false
limit: 0
high:
enabled: false
limit: 0
medium:
enabled: false
limit: 0
low:
enabled: false
limit: 0
epssLimit:
enabled: false
score: 0
kevLimitEnabled: false
cveLimit:
enabled: false
cves: []
epssRiskAcceptance:
enabled: false
score: 0
cveRiskAcceptance:
enabled: false
cves: []
trivy:
severityLimit:
critical:
enabled: false
limit: 0
high:
enabled: false
limit: 0
medium:
enabled: false
limit: 0
low:
enabled: false
limit: 0
epssLimit:
enabled: false
score: 0
kevLimitEnabled: false
cveLimit:
enabled: false
cves: []
epssRiskAcceptance:
enabled: false
score: 0
cveRiskAcceptance:
enabled: false
cves: []
osv-scanner:
severityLimit:
critical:
enabled: false
limit: 0
high:
enabled: false
limit: 0
medium:
enabled: false
limit: 0
low:
enabled: false
limit: 0
epssLimit:
enabled: false
score: 0
kevLimitEnabled: false
cveLimit:
enabled: false
cves: []
epssRiskAcceptance:
enabled: false
score: 0
cveRiskAcceptance:
enabled: false
cves: []
semgrep:
severityLimit:
error:
enabled: false
limit: 0
warning:
enabled: false
limit: 0
info:
enabled: false
limit: 0
impactRiskAcceptance:
enabled: false
high: false
medium: false
low: false
gitleaks:
limitEnabled: false
sarif:
severityLimit:
critical:
enabled: false
limit: 0
high:
enabled: false
limit: 0
medium:
enabled: false
limit: 0
low:
enabled: false
limit: 0
ruleLimit:
enabled: false
rules: []
ruleRiskAcceptance:
enabled: false
rules: []
coverage:
lineThreshold: 0
functionThreshold: 0
branchThreshold: 0
version and metadata
version is the string "1". metadata.tags is a list of strings. Neither one changes validation.
Grype, CycloneDX, Trivy, and osv-scanner
grype, cyclonedx, trivy, and osv-scanner use the same fields. Trivy scores vulnerability entries. Misconfigurations, secrets, and licenses in the Trivy JSON are ignored. A Trivy id matches VulnerabilityID and each VendorIDs entry.
osv-scanner counts one finding per vulnerability group. Aliases of that group are not counted again. License-only packages are skipped. max_severity is a CVSS base score: 9.0 and above is critical, 7.0 high, 4.0 medium, 0.1 low, and anything lower is unknown. The words CRITICAL, HIGH, MEDIUM, LOW, MODERATE, and UNKNOWN are also accepted. MODERATE is medium. A CVSS vector with no numeric score is unknown. database_specific.severity is used when max_severity is empty. Deny, allow, and KEV match the OSV id or any alias. EPSS and KEV look up the first id that starts with CVE-.
severityLimit has critical, high, medium, and low. Each has enabled and limit. limit is a count. The report fails when the number of findings at that severity is greater than limit. enabled: true and limit: 0 allows none. enabled: false skips that severity.
epssLimit.score and epssRiskAcceptance.score are EPSS ratios from 0 to 1, the same scale as the FIRST CSV. The limit fails when a CVE’s score is greater than score. Risk acceptance removes a CVE when score is greater than that CVE’s score. See Validation for the order and the equal-score cases.
kevLimitEnabled fails the report when any remaining CVE is in the CISA catalog.
cveLimit and cveRiskAcceptance each have enabled and cves. A CVE entry is id plus an optional metadata.tags list. id is compared without regard to case.
grype:
cveLimit:
enabled: true
cves:
- id: CVE-2024-0001
metadata:
tags:
- denied
cveRiskAcceptance:
enabled: true
cves:
- id: CVE-2023-5678
metadata:
tags:
- accepted
Semgrep
severityLimit has error, warning, and info. Each has enabled and limit, with the same meaning as the Grype counts.
impactRiskAcceptance has enabled, high, medium, and low. When enabled is true, a finding is removed when its impact matches a level whose value is true. high, medium, and low are separate switches.
Gitleaks
limitEnabled: true fails validation when the report contains any finding. false skips the check. There is no count.
SARIF
sarif is for any SARIF 2.1.0 report. Semgrep’s own JSON still uses semgrep. semgrep --sarif uses sarif.
severityLimit has critical, high, medium, and low. Each has enabled and limit, with the same count rule as Grype.
The severity comes from the SARIF property security-severity when a result or its rule has one. The value is a number from 0 to 10, or a numeric string. The ranges are the ones GitHub code scanning uses:
- 9.0 and above: critical
- 7.0 to 8.9: high
- 4.0 to 6.9: medium
- above 0 and below 4.0: low
- 0: none, and the severity limit does not count it
A result property wins over the same property on the rule. When neither is set, gatecheck uses the SARIF level. A missing result level uses the rule’s defaultConfiguration.level, then warning.
error: highwarning: mediumnote: lownone: the result is ignored
ruleLimit is the deny list. ruleRiskAcceptance is the allow list. Each has enabled and rules. A rule entry is id plus an optional metadata.tags list. id is compared without regard to case.
sarif:
ruleLimit:
enabled: true
rules:
- id: CKV_AWS_21
metadata:
tags:
- denied
ruleRiskAcceptance:
enabled: true
rules:
- id: B101
metadata:
tags:
- accepted
See Validation for which results are counted and the order of the rules.
Coverage
lineThreshold, functionThreshold, and branchThreshold are ratios from 0 to 1:
- line coverage is covered lines divided by total lines
- function coverage is covered functions divided by total functions
- branch coverage is covered branches divided by total branches
The report fails when its ratio is less than the threshold. 0.8 is 80 percent. 80.0 fails a report whose real line coverage is 0.8, because 0.8 is less than 80.
There is no enabled flag. The default 0 allows any coverage, because a ratio is never less than 0.
gatecheck list prints these numbers as percents in the table footer. The config still wants the ratio.
A tighter file
version: "1"
metadata:
tags:
- ci
grype:
severityLimit:
critical:
enabled: true
limit: 0
high:
enabled: true
limit: 5
epssLimit:
enabled: true
score: 0.5
kevLimitEnabled: true
semgrep:
severityLimit:
error:
enabled: true
limit: 0
warning:
enabled: true
limit: 10
impactRiskAcceptance:
enabled: true
high: false
medium: true
low: true
gitleaks:
limitEnabled: true
coverage:
lineThreshold: 0.8
functionThreshold: 0.75
branchThreshold: 0.7
Fields left out of this file keep the defaults from config init.
Library Usage
The CLI is a thin wrapper around github.com/gatecheckdev/gatecheck/pkg/gatecheck.
import "github.com/gatecheckdev/gatecheck/pkg/gatecheck"
NewDefaultConfigreturns the same defaults asgatecheck config init: rules disabled, coverage thresholds0.NewConfigDecoderreads.yaml,.yml,.json, or.toml. The extension selects the format.NewConfigEncoderwrites a config. Pass.yaml,.yml,.json, or.toml, including the dot.Validatetakes the config, a reader, and the filename. The bytes select the report type. The filename is the fallback, with the same words as the CLI.Listwrites a table. A Grype, CycloneDX, SARIF, Semgrep, Gitleaks, Trivy, or osv-scanner report with no findings writes one sentence instead, such asNo gitleaks findings,No trivy vulnerabilities, orNo osv-scanner vulnerabilities.WithDisplayFormat("markdown")matches--markdownand writes that same sentence when the report is empty.WithEPSSmatches--epssand takes an open CSV file or a URL.CreateBundle,AppendToBundle, andRemoveFromBundlearebundle create,bundle add, andbundle remove.DownloadEPSSandDownloadKEVwrite the API payloads.WithEPSSURL,WithKEVURL,WithEPSSFile, andWithKEVFileoverride the defaults.
Report types are described in Supported Reports. Config fields are described in Configuration.