Gatecheck

Gatecheck

CICD Pipeline Go Reference Go Report Card

Gatecheck Logo

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.

Gatecheck Version

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.

Gatecheck List

Validation

gatecheck validate --help

Gatecheck Validate

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

Gatecheck Bundle

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

  1. Download the Binary: Visit the Gatecheck GitHub releases page at https://github.com/gatecheckdev/gatecheck/releases and download the latest version for your operating system.

  2. Unpack the Binary (if necessary): For Windows and Linux, you may need to unpack the .zip or .tar.gz file.

  3. Move the Binary to a Bin Directory:

    • Windows: Move gatecheck.exe to a directory within your PATH, such as C:\Windows.
    • macOS/Linux: Move gatecheck to a location in your PATH, such as /usr/local/bin. You can use the command mv gatecheck /usr/local/bin in the terminal.
  4. Verify Installation: Open a terminal or command prompt and type gatecheck version or gatecheck --version to ensure the application is installed correctly.

Option 2: Building from Source

  1. Clone the Repository: Clone the Gatecheck repository to your local machine using Git:

    git clone https://github.com/gatecheckdev/gatecheck
    
  2. Navigate to the Repository Directory:

    cd gatecheck
    
  3. Install Task: Ensure you have Task installed.

  4. Build and Install: Run:

    task build
    task install
    

    task build writes ./bin/gatecheck. task install copies that binary to INSTALL_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
    
  5. 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 version prints the build information. gatecheck --version does the same. The --version flag is only on the root command.
  • gatecheck config init prints a default config. gatecheck config convert rewrites one into another format.
  • gatecheck list (aliases ls and print) prints one report. gatecheck list-all prints several.
  • gatecheck validate compares one report, or one bundle, to the config.
  • gatecheck bundle create, bundle add, and bundle remove manage a bundle.
  • gatecheck download epss and gatecheck download kev write the upstream data to standard output. EPSS files are cached until the published date changes.
  • gatecheck bootstrap installs Grype, Syft, Gitleaks, semgrep’s experimental osemgrep CLI, Trivy, and osv-scanner. gatecheck grype, syft, gitleaks, semgrep, osemgrep, trivy, and osv-scanner run those programs. See Bootstrap.
  • gatecheck update (aliases self-update and upgrade) replaces this binary with a GitHub release after checking the archive checksum. gatecheck update --check only prints the current and latest versions.
  • gatecheck agent-guide (alias llm) prints a markdown guide for coding agents.
  • gatecheck completion prints 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:

  • 0 when the command succeeds. With validate --audit, an error returned by the check also exits 0.
  • 1 when a report misses a configured threshold and --audit is off.
  • 255 for a missing file, a rejected command line, or a check error when --audit is off.
  • The scanner commands return that program’s own status. A scanner that is neither installed nor on PATH exits 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/gatecheck when XDG_DATA_HOME is 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 is grype,syft,gitleaks,semgrep,trivy,osv-scanner. Names are lowercased. osemgrep means semgrep. 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.

ToolReleaseAsset name
Grypeanchore/grypegrype_<version>_<os>_<arch>.tar.gz, or .zip on Windows
Syftanchore/syftsyft_<version>_<os>_<arch>.tar.gz, or .zip on Windows
Gitleaksgitleaks/gitleaksgitleaks_<version>_<os>_<arch>.tar.gz, or .zip on Windows
Trivyaquasecurity/trivytrivy_<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_amd64 and osv-scanner_linux_arm64
  • osv-scanner_darwin_amd64 and osv-scanner_darwin_arm64
  • osv-scanner_windows_amd64.exe and osv-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 as gatecheck 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 is yaml. 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 is gatecheck.yaml. The extension picks the decoder (.yaml, .yml, .json, .toml).
  • -o, --output: format to write. Same accepted values as config init. The default is yaml.
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_FILENAME is the same setting.
  • --epss-url: EPSS API URL. An empty value uses https://epss.cyentia.com. GATECHECK_EPSS_URL is the same setting.
  • --epss-cache-dir: cache directory for that download. GATECHECK_EPSS_CACHE_DIR is the same setting.
  • --epss-no-cache: download on every run. GATECHECK_EPSS_CACHE=off does 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-filename flag. GATECHECK_EPSS_URL overrides the API. GATECHECK_EPSS_FILENAME is 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_DIR is the same setting.
  • --epss-no-cache: download on every run. GATECHECK_EPSS_CACHE=off does the same.

gatecheck validate

gatecheck validate [FILE]

FILE is required. The config is a flag.

  • -f, --config: config file. GATECHECK_CONFIG_FILENAME is the same setting. With neither, the built-in default config is used (every rule disabled, coverage thresholds 0).
  • --epss-filename: EPSS CSV to use when an EPSS rule is enabled. GATECHECK_EPSS_FILENAME is the same setting.
  • --epss-cache-dir: cache directory used when that CSV is downloaded. GATECHECK_EPSS_CACHE_DIR is the same setting.
  • --epss-no-cache: download on every run. GATECHECK_EPSS_CACHE=off does 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_TAG is 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 uses https://epss.cyentia.com. GATECHECK_EPSS_URL is the same setting.
  • --epss-cache-dir: cache directory. GATECHECK_EPSS_CACHE_DIR is the same setting.
  • --epss-no-cache: download on every run. GATECHECK_EPSS_CACHE=off does 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 uses https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json. GATECHECK_KEV_URL is 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. Default grype,syft,gitleaks,semgrep,trivy,osv-scanner. osemgrep selects 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

VariableCommandsSame as
GATECHECK_CONFIG_FILENAMEvalidate--config
GATECHECK_EPSS_FILENAMElist, validate--epss-filename
GATECHECK_EPSS_URLdownload epss, list, list-all, validate--epss-url on download epss and list
GATECHECK_EPSS_CACHE_DIRdownload epss, list, list-all, validate--epss-cache-dir
GATECHECK_EPSS_CACHEdownload epss, list, list-all, validate--epss-no-cache when the value is off
GATECHECK_KEV_URLdownload kev, validate--kev-url on download kev
GATECHECK_BUNDLE_TAGbundle create, bundle add--tag, as a comma-separated list
GATECHECK_HOMEbootstrap, grype, syft, gitleaks, semgrep, osemgrep, trivy, osv-scannerdata 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

Screenshot Example Grype 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

Screenshot Example List

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 none is 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 with validation 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.

  1. CVE limit. cveLimit, when enabled, fails if any listed id is in the report. Ids are compared without regard to case.
  2. 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.
  3. CVE risk acceptance. Matching ids are removed and skip the remaining rules.
  4. KEV limit. When kevLimitEnabled is true, a CVE that is in the catalog fails the report. The catalog is --kev-filename or, with no file, the CISA feed. GATECHECK_KEV_URL overrides the feed. There is no --kev-url flag on validate.
  5. EPSS risk acceptance. A CVE is removed when the configured score is 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.
  6. 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-filename or GATECHECK_EPSS_FILENAME, or from the API. GATECHECK_EPSS_URL overrides the API. There is no --epss-url flag on validate.
  7. Severity limit. For each enabled severity, the report fails when the count is greater than limit. limit: 0 allows none. Counts that are equal to the limit pass. Grype, CycloneDX, Trivy, and osv-scanner severities are critical, high, medium, and low. negligible and unknown have 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

  1. Findings whose severity limit is disabled are dropped.
  2. Impact risk acceptance. When enabled, a finding is removed when its impact is high, medium, or low and that level’s boolean is true. The three booleans are independent.
  3. Severity limit. Severities are error, warning, and info. The report fails when an enabled severity has more findings than its limit.

SARIF

Rules run in this order. A failure returns immediately, except where a rule only removes findings.

  1. 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.
  2. Disabled severities. Findings whose severity limit is disabled are dropped. none has no limit field and stays in the report, but the severity rule does not count it.
  3. Rule risk acceptance. Matching rule ids are removed and skip the remaining rules.
  4. Severity limit. For each enabled severity, the report fails when the count is greater than limit. limit: 0 allows none. Counts that are equal to the limit pass. Severities are critical, high, medium, and low.

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:

  1. A gzipped tar that contains gatecheck-manifest.json is a Gatecheck bundle.
  2. bomFormat of CycloneDX is CycloneDX JSON. This wins when the name contains grype, syft, trivy, or osv, and it wins when the tool that wrote the BOM was Grype, Syft, Trivy, or another tool.
  3. SARIF 2.1.0. The top-level version is the string 2.1.0 and runs is an array. A $schema that mentions SARIF is enough when runs is missing or null.
  4. Grype JSON. descriptor.name is grype, or matches is a non-empty array of objects with vulnerability and artifact.
  5. Syft JSON. descriptor.name is syft, or schema.url points at the Syft schema. list and validate then return an error. Syft JSON is not implemented. A Syft CycloneDX BOM is CycloneDX, not Syft.
  6. Semgrep JSON. results is an array of objects with check_id, or results and errors are both arrays. Semgrep’s SARIF output is SARIF, not this type.
  7. Gitleaks JSON. A non-empty array of objects with RuleID and one of File, Commit, or Fingerprint.
  8. Trivy JSON (--format json). SchemaVersion is a number, and ArtifactType is set or Results is an array. Vulnerability entries are listed and validated. Misconfigurations, secrets, and licenses in the same file are ignored.
  9. osv-scanner JSON (osv-scanner scan source --format json). results is a non-empty array of objects with a packages array. One finding per vulnerability group. Aliases of that group are not counted again. License-only packages are skipped. Semgrep is checked first, so a check_id stays Semgrep.
  10. LCOV text. A line starts with SF: and the file also has DA:, LF:, or end_of_record.
  11. Clover XML. An XML document with clover= or a <clover element.
  12. 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:

  1. grype
  2. cyclonedx. This is before trivy, so an ambiguous file named cyclonedx-trivy-sbom.json is CycloneDX.
  3. semgrep
  4. gitleaks
  5. trivy
  6. osv. osv-scanner-report.json matches. OSV-scanner.json does not.
  7. syft
  8. sarif
  9. bundle. list also accepts a name containing gatecheck. validate requires the word bundle for this fallback. A real bundle is still detected from its contents when the name is project.gcb.
  10. Coverage, when the name contains lcov, clover, cobertura, or coverage, 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:

Reportlistvalidatebundle
Grypeyesyesyes
CycloneDX JSONyesyesyes
SARIF 2.1.0yesyesyes
Semgrep JSONyesyesyes
Gitleaksyesyesyes
Trivyyesyesyes
osv-scanneryesyesyes
LCOV, Clover, Coberturayesyesyes
Syft JSONerrorerrorthe file is stored, and validation skips that label
Bundlewhen the contents are a bundle, or the name contains bundle or gatecheckwhen the contents are a bundle, or the name contains bundleyes, 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: high
  • warning: medium
  • note: low
  • none: 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"
  • NewDefaultConfig returns the same defaults as gatecheck config init: rules disabled, coverage thresholds 0.
  • NewConfigDecoder reads .yaml, .yml, .json, or .toml. The extension selects the format.
  • NewConfigEncoder writes a config. Pass .yaml, .yml, .json, or .toml, including the dot.
  • Validate takes 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.
  • List writes a table. A Grype, CycloneDX, SARIF, Semgrep, Gitleaks, Trivy, or osv-scanner report with no findings writes one sentence instead, such as No gitleaks findings, No trivy vulnerabilities, or No osv-scanner vulnerabilities. WithDisplayFormat("markdown") matches --markdown and writes that same sentence when the report is empty. WithEPSS matches --epss and takes an open CSV file or a URL.
  • CreateBundle, AppendToBundle, and RemoveFromBundle are bundle create, bundle add, and bundle remove.
  • DownloadEPSS and DownloadKEV write the API payloads. WithEPSSURL, WithKEVURL, WithEPSSFile, and WithKEVFile override the defaults.

Report types are described in Supported Reports. Config fields are described in Configuration.