GitLab CI
Integrate ScanRook into your GitLab CI/CD pipeline. Scan container images on every push, produce structured vulnerability reports, and gate merge requests on severity thresholds.
Complete pipeline
Copy this to .gitlab-ci.yml in the root of your repository.
stages:
- build
- scan
variables:
SCANROOK_VERSION: "latest"
build-image:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker save $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -o image.tar
artifacts:
paths:
- image.tar
expire_in: 1 hour
scanrook-scan:
stage: scan
image: ubuntu:24.04
dependencies:
- build-image
before_script:
- apt-get update && apt-get install -y curl jq
- curl -fsSL https://scanrook.sh/install | bash
script:
- |
scanrook scan \
--file ./image.tar \
--mode deep \
--format json \
--out report.json
- |
echo "=== Scan Summary ==="
jq '.summary' report.json
- |
CRITICAL=$(jq '.summary.critical // 0' report.json)
HIGH=$(jq '.summary.high // 0' report.json)
echo "Critical: $CRITICAL, High: $HIGH"
if [ "$CRITICAL" -gt 0 ] || [ "$HIGH" -gt 0 ]; then
echo "ERROR: Found $CRITICAL critical and $HIGH high severity vulnerabilities"
jq '.findings[] | select(.severity == "CRITICAL" or .severity == "HIGH") | {cve, package: .package.name, version: .package.version, severity, confidence}' report.json
exit 1
fi
artifacts:
paths:
- report.json
reports:
dotenv: scanrook.env
when: always
expire_in: 30 days
variables:
NVD_API_KEY: $NVD_API_KEYStage breakdown
What each stage and job does.
build-image
Builds the Docker image and saves it as a tar file artifact. The docker:dind service provides Docker-in-Docker for the build. The tar is passed to the scan stage via GitLab artifacts.
scanrook-scan
Installs ScanRook via the shell installer, scans the saved image tar, prints the summary, and exits with code 1 if critical or high vulnerabilities are found. The JSON report is saved as an artifact with a 30-day retention.
Run only on merge requests
Limit scans to merge request pipelines to save CI minutes.
scanrook-scan:
stage: scan
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# ... rest of job configCaching between runs
Speed up scans by caching vulnerability API responses across pipeline runs.
scanrook-scan:
cache:
key: scanrook-cache
paths:
- .scanrook-cache/
variables:
SCANNER_CACHE: "$CI_PROJECT_DIR/.scanrook-cache"
# ... rest of job configSet SCANNER_CACHE to a path inside $CI_PROJECT_DIR so GitLab can cache it between runs. The scanrook-cache key ensures the cache is shared across all branches.
Tips
Best practices for GitLab CI integration.
- Store
NVD_API_KEYas a CI/CD variable (Settings > CI/CD > Variables). Mark it as masked and protected. - Use
when: alwayson the artifacts block so the report is saved even when the scan fails. - For large images, increase the artifact expiration on the build stage or use GitLab's container registry to avoid re-building.
- Filter findings by confidence in the gate script to avoid failing on heuristic-only matches. Add
select(.confidence == "ConfirmedInstalled")to thejqfilter. - Consider running
scanrook db updatebefore the scan to pre-warm the cache, especially in cold environments without a persistent cache.