Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Eljakani/ward/llms.txt
Use this file to discover all available pages before exploring further.
Ward is designed to integrate seamlessly into CI/CD pipelines. Run security scans automatically on every push or pull request, fail builds when security issues are detected, and upload results to GitHub Code Scanning.
Exit Codes and Fail Thresholds
Ward returns exit code 1 when security findings exceed your specified severity threshold, allowing you to gate deployments based on security posture.
Using --fail-on
The --fail-on flag sets the minimum severity level that will cause Ward to exit with code 1:
# Exit code 1 if any High or Critical findings exist
ward scan . --output json --fail-on high
# Fail on any finding (including Info)
ward scan . --output json --fail-on info
# Fail only on Critical findings
ward scan . --output json --fail-on critical
The severity threshold is inclusive. --fail-on medium will fail on Medium, High, and Critical findings.
Severity Levels
Ward recognizes five severity levels (in ascending order):
- Info — Informational findings (e.g., missing
.env file)
- Low — Low-risk issues (e.g., empty database password)
- Medium — Medium-risk issues (e.g., non-production APP_ENV)
- High — High-risk issues (e.g.,
APP_DEBUG=true, hardcoded passwords)
- Critical — Critical security vulnerabilities (e.g., empty APP_KEY, eval() usage)
Baseline Management for CI
Baselines let you suppress known findings and only fail builds on new security issues. This is essential when introducing Ward into an existing project with legacy findings.
Generate initial baseline
On first run, create a baseline file containing current findings:ward scan . --output json --update-baseline .ward-baseline.json
This creates .ward-baseline.json with fingerprints of all current findings. Commit baseline to repository
Commit the baseline file to your repository:git add .ward-baseline.json
git commit -m "Add Ward security baseline"
Use baseline in CI
Configure your CI pipeline to use the baseline:ward scan . --output json --baseline .ward-baseline.json --fail-on high
Only findings not in the baseline will be reported. The build fails only if new High or Critical findings are discovered. Update baseline when needed
After fixing findings or acknowledging new ones:ward scan . --output json --update-baseline .ward-baseline.json
git add .ward-baseline.json
git commit -m "Update Ward baseline"
GitHub Actions
Add Ward to your GitHub Actions workflow to scan on every push and pull request.
Basic Workflow
Create .github/workflows/ward.yml:
name: Ward Security Scan
on: [push, pull_request]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Ward
run: go install github.com/eljakani/ward@latest
- name: Run Ward
run: ward init && ward scan . --output json
With SARIF Upload (GitHub Code Scanning)
Upload Ward’s SARIF report to GitHub Code Scanning to see security findings directly in your pull requests:
name: Ward Security Scan
on: [push, pull_request]
jobs:
security-scan:
runs-on: ubuntu-latest
permissions:
security-events: write # Required for SARIF upload
contents: read
steps:
- uses: actions/checkout@v4
- name: Install Ward
run: go install github.com/eljakani/ward@latest
- name: Run Ward
run: ward init && ward scan . --output json,sarif
- name: Upload SARIF to GitHub Code Scanning
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ward-report.sarif
The if: always() ensures SARIF upload happens even if Ward exits with code 1 due to findings.
With Baseline and Fail Threshold
Gate deployments based on new security findings:
name: Ward Security Scan
on: [push, pull_request]
jobs:
security-scan:
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Install Ward
run: go install github.com/eljakani/ward@latest
- name: Initialize Ward
run: ward init
- name: Run Ward with baseline
run: |
ward scan . --output json,sarif \
--baseline .ward-baseline.json \
--fail-on high
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ward-report.sarif
This workflow:
- Installs Ward from the latest release
- Initializes Ward configuration
- Runs a scan using the committed baseline
- Fails the build if any new High or Critical findings are detected
- Uploads SARIF results to GitHub Code Scanning regardless of pass/fail
Caching Ward Installation
Speed up your workflow by caching the Go installation:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.24'
cache: true
- name: Install Ward
run: go install github.com/eljakani/ward@latest
GitLab CI
Add Ward to your .gitlab-ci.yml:
Basic GitLab Pipeline
ward-scan:
image: golang:latest
script:
- go install github.com/eljakani/ward@latest
- ward init && ward scan . --output json
artifacts:
paths:
- ward-report.*
when: always
With Baseline and Fail Threshold
ward-scan:
image: golang:latest
script:
- go install github.com/eljakani/ward@latest
- ward init
- ward scan . --output json,sarif --baseline .ward-baseline.json --fail-on high
artifacts:
paths:
- ward-report.*
when: always
allow_failure: false
Set allow_failure: false to ensure the pipeline fails when Ward detects new High or Critical findings.
Bitbucket Pipelines
Add to your bitbucket-pipelines.yml:
pipelines:
default:
- step:
name: Ward Security Scan
image: golang:latest
script:
- go install github.com/eljakani/ward@latest
- ward init && ward scan . --output json,sarif --fail-on high
artifacts:
- ward-report.*
Azure DevOps
Create azure-pipelines.yml:
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: GoTool@0
inputs:
version: '1.24'
- script: |
go install github.com/eljakani/ward@latest
ward init
ward scan . --output json,sarif --fail-on high
displayName: 'Run Ward Security Scan'
- task: PublishBuildArtifacts@1
condition: always()
inputs:
pathToPublish: 'ward-report.json'
artifactName: 'ward-reports'
CircleCI
Add to .circleci/config.yml:
version: 2.1
jobs:
security-scan:
docker:
- image: cimg/go:1.24
steps:
- checkout
- run:
name: Install Ward
command: go install github.com/eljakani/ward@latest
- run:
name: Run Ward
command: |
ward init
ward scan . --output json,sarif --baseline .ward-baseline.json --fail-on high
- store_artifacts:
path: ward-report.json
destination: ward-report.json
workflows:
security:
jobs:
- security-scan
Docker
Run Ward in a Docker container for consistent CI environments:
FROM golang:1.24 AS ward
RUN go install github.com/eljakani/ward@latest
WORKDIR /workspace
COPY . .
RUN ward init && ward scan . --output json --fail-on high
Or use as a CI step:
- name: Run Ward in Docker
run: |
docker run --rm -v $(pwd):/workspace golang:1.24 sh -c \
"cd /workspace && go install github.com/eljakani/ward@latest && ward init && ward scan . --output json"
Ward can generate multiple report formats simultaneously. Configure output formats in the --output flag:
# Generate JSON and SARIF
ward scan . --output json,sarif
# Generate all formats
ward scan . --output json,sarif,html,markdown
Available formats:
- json — Machine-readable format (always generated as baseline)
- sarif — SARIF 2.1.0 format for GitHub Code Scanning, IDEs, and security tools
- html — Standalone visual report with dark theme
- markdown — Text-based report, great for pull request comments
Troubleshooting
Ward exits with code 0 despite findings
Ensure you’re using the --fail-on flag:
ward scan . --output json --fail-on high
Without --fail-on, Ward always exits with code 0 regardless of findings.
SARIF upload fails in GitHub Actions
Ensure your workflow has the required permissions:
permissions:
security-events: write # Required for SARIF upload
contents: read
Baseline file not found
Ensure .ward-baseline.json is committed to your repository:
git add .ward-baseline.json
git commit -m "Add Ward baseline"
git push
Go installation is slow
Use Go version caching in GitHub Actions:
- uses: actions/setup-go@v4
with:
go-version: '1.24'
cache: true
Or cache the Ward binary directly:
- uses: actions/cache@v3
with:
path: ~/go/bin/ward
key: ward-${{ hashFiles('go.sum') }}