CI and integrations
Ways to run openaudit without installing it by hand. The Docker image is the only one that also brings the scanners (gitleaks, Semgrep, Trivy and so on); the others use whatever is on PATH, and openaudit doctor shows what is missing.
GitHub Action
The repository is also a GitHub Action. On pull requests it reports only findings in changed files, uploads SARIF to code scanning, attaches the reports as an artifact and writes a job summary:
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # diff mode compares against the base branch
- uses: wezter96/openaudit@main # pin to a commit SHA in real use
with:
fail-on: highInputs: target, fail-on, diff (defaults to the PR base; none audits everything), only, exclude, config, upload-sarif, upload-report. Outputs: score, grade, report-dir.
Elsewhere, run the CLI: bunx openaudit . --diff origin/main -f html,sarif -o openaudit-report --fail-on high. --fail-on <severity> sets the exit code, and --baseline previous.json reports only findings that are new since an earlier run. This repository audits itself in ci.yml and publishes the result with pages.yml.
Inputs
| Input | Default | Description |
|---|---|---|
target | . | Directory, URL or image: to audit. |
fail-on | high | Fail the step on findings at or above this severity (critical, high, medium, low, info, none). |
diff | empty | Only report findings in files changed since this git ref. Defaults to the pull request's base branch on pull_request events; "none" audits everything. Needs history: use actions/checkout with fetch-depth 0. |
only | empty | Comma-separated auditor ids or prefixes to run (e.g. "code,iac"). |
exclude | empty | Comma-separated auditor ids or prefixes to skip. |
config | empty | Trusted config file (openaudit.config.json) for opt-in auditors and settings. |
upload-sarif | true | Upload SARIF to GitHub code scanning (needs security-events write). |
upload-report | true | Upload the HTML, JSON, SARIF and Markdown reports as a workflow artifact. |
Outputs
| Output | Description |
|---|---|
score | Overall score, 0-100. |
grade | Overall grade, A-F. |
report-dir | Directory holding the reports. |
SARIF and code scanning
The simplest setup is the bundled GitHub Action (action.yml at the repository root). On pull requests it audits only the files the PR changed, uploads SARIF, attaches the reports (HTML, JSON, SARIF, Markdown) as an artifact, writes a job summary and fails on findings at or above fail-on. Inputs: target, fail-on, diff (defaults to the PR base; none audits everything), only, exclude, config, upload-sarif, upload-report. Outputs: score, grade, report-dir. Check out with fetch-depth: 0 so the base branch's history is available. The job needs security-events: write.
To run the CLI directly instead:
- uses: oven-sh/setup-bun@v2
- name: openaudit
run: bunx openaudit . --format sarif,markdown --out openaudit --fail-on high
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: openaudit/openaudit-report.sarif
category: openaudit
- name: Job summary
if: always()
run: cat openaudit/openaudit-report.md >> "$GITHUB_STEP_SUMMARY"Run the audit from the repository root, so that SARIF file paths line up with the files in the repository. The job needs the security-events: write permission to upload SARIF.
Docker
ghcr.io/wezter96/openaudit bundles openaudit with the free scanners, pinned to exact versions. Images are multi-arch (linux/amd64, linux/arm64) and ship with provenance and an SBOM.
| Tag | Contents |
|---|---|
latest, 1.2.3, 1.2, edge (main) | slim: openaudit and the scanners below |
latest-full, 1.2.3-full, edge-full | slim plus Chromium, Lighthouse and pa11y, for --browser and the web auditors |
# Audit the current directory. Run as yourself: git refuses repositories owned by
# another user, and reports are written as you
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/src" -w /src \
ghcr.io/wezter96/openaudit . -f html,sarif -o openaudit-report --fail-on high
# Audit a live site with a real browser
docker run --rm ghcr.io/wezter96/openaudit:latest-full https://example.com --browser
# See which tools are installed
docker run --rm ghcr.io/wezter96/openaudit doctorIncluded: gitleaks, trufflehog, osv-scanner, Trivy, Grype, Syft, hadolint, actionlint, kube-linter, ShellCheck, zizmor, OpenSSF Scorecard, oxlint, Biome, Spectral, jscpd, Semgrep, Bandit, pip-audit, Checkov, Ruff, mobsfscan. The versions are the ARGs at the top of the Dockerfile.
Not included: ZAP (needs Docker), Prowler (needs cloud credentials), the Go, Rust and Ruby linters (gosec, staticcheck, govulncheck, golangci-lint, clippy, cargo-audit, brakeman need their language toolchain), and tsc, ESLint, knip and mypy (need the audited project's own dependencies). Those auditors report skipped with an install hint. Network-backed scanners (Trivy, OSV, Semgrep rules) need outbound access; add --offline to forbid it.
Always pass --user "$(id -u):$(id -g)". The image does not disable git's ownership check (safe.directory), which protects scanners from a hostile repository's .git/config, so a mount owned by another uid makes git-based features such as --diff fail with "dubious ownership". GitLab runners and pre-commit already match ownership (see below).
Build it yourself: docker build -t openaudit . (slim) or docker build --target full -t openaudit:full ..
GitLab CI
include:
- remote: https://raw.githubusercontent.com/wezter96/openaudit/main/integrations/gitlab/openaudit.gitlab-ci.yml
variables:
OPENAUDIT_FAIL_ON: high # optionalOn merge requests the job audits only changed files (--diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME); on the default branch and schedules it audits everything. Results:
- openaudit report link on the MR: the artifact folder with the HTML, SARIF, JSON and Markdown reports.
- Code Quality widget on the MR, converted from the findings. GitLab's
reports:sastexpects GitLab's own schema rather than SARIF, so SARIF stays a plain artifact.
The job runs as root on a root-owned checkout, so ownership matches. Pin OPENAUDIT_IMAGE to a version tag for reproducible runs. See the comments in the template for the other variables.
pre-commit
repos:
- repo: https://github.com/wezter96/openaudit
rev: main # pin to a tag or commit
hooks:
- id: openaudit # needs Bun on PATH
# - id: openaudit-docker # or: the Docker image, nothing else to installThe hooks audit the whole working tree with --offline --fail-on high, so staged changes are covered and a commit stays quick. They do not use --diff: it compares commits (<ref>...HEAD) and staged changes are not committed yet, so --diff HEAD would find nothing. To check a branch's committed changes instead, run the hook on pre-push with your own arguments:
- id: openaudit
stages: [pre-push]
args: [".", "--diff", "origin/main", "--fail-on", "high", "--quiet"]openaudit-docker runs the container with your uid and gid (pre-commit does this itself), so ownership matches. Offline mode skips the checks that query advisory databases; CI covers those.