openauditB85out of 100: openaudit's audit of itself

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: high

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.

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

InputDefaultDescription
target.Directory, URL or image: to audit.
fail-onhighFail the step on findings at or above this severity (critical, high, medium, low, info, none).
diffemptyOnly 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.
onlyemptyComma-separated auditor ids or prefixes to run (e.g. "code,iac").
excludeemptyComma-separated auditor ids or prefixes to skip.
configemptyTrusted config file (openaudit.config.json) for opt-in auditors and settings.
upload-sariftrueUpload SARIF to GitHub code scanning (needs security-events write).
upload-reporttrueUpload the HTML, JSON, SARIF and Markdown reports as a workflow artifact.

Outputs

OutputDescription
scoreOverall score, 0-100.
gradeOverall grade, A-F.
report-dirDirectory 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.

TagContents
latest, 1.2.3, 1.2, edge (main)slim: openaudit and the scanners below
latest-full, 1.2.3-full, edge-fullslim 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 doctor

Included: 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   # optional

On 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:sast expects 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 install

The 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.