squirrelscan
GitHub

Continuous Integration

Gate your CI builds on squirrelscan audits: GitHub Actions, GitLab, and generic runners

Run squirrelscan in CI to catch audit problems (performance, security, content, and more) before they ship. Set thresholds with --fail-on and the audit exits non-zero when one trips, so your pipeline fails like any other check.

--fail-on compares each run against the thresholds you set, not against an earlier audit. There is no baseline gating: the build does not fail because a score dropped since the last run, only because it is below your threshold. To see what changed between two audits, use squirrel report --regression-since, which prints the comparison but does not set a failing exit code.

Exit codes

squirrel audit uses distinct exit codes so CI can tell a tripped threshold apart from a broken run:

CodeMeaning
0Audit ran and every --fail-on threshold passed
2Audit ran but a --fail-on threshold tripped
1Operational error (bad flags, a crash, a site that answered with an error, etc.)
3The audited page was blocked (a WAF or bot manager, or a bare 403 or 429), so nothing was audited. See blocked by a WAF or bot manager
5The start URL could not be reached (DNS, timeout, connection or TLS failure), so nothing was audited. See unreachable start URLs

Gate your build with --fail-on; quote each expression, since shells treat bare </> as redirection:

squirrel audit https://example.com --fail-on 'score<90' --fail-on 'severity>=error'

GitHub Actions

The quickest path is the official squirrelscan audit action, available on the GitHub Marketplace:

name: Audit
on: [pull_request]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: squirrelscan/audit-action@v1
        with:
          url: https://staging.example.com
          fail-on: "score<90,severity>=error"
          token: ${{ secrets.SQUIRRELSCAN_API_KEY }}   # optional
          github-token: ${{ secrets.GITHUB_TOKEN }}   # optional PR comment

Prefer no action? Install the CLI directly:

      - run: |
          curl -fsSL --connect-timeout 10 --max-time 120 https://install.squirrelscan.com | bash
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"  # resolve squirrel in later steps (self-hosted)
      - run: squirrel audit https://staging.example.com --fail-on 'score<90'
        env:
          SQUIRRELSCAN_API_KEY: ${{ secrets.SQUIRRELSCAN_API_KEY }}

GitLab CI

audit:
  image: ubuntu:latest
  script:
    - apt-get update && apt-get install -y curl
    - curl -fsSL --connect-timeout 10 --max-time 120 https://install.squirrelscan.com | bash
    - export PATH="$HOME/.local/bin:$PATH"
    - squirrel audit "$AUDIT_URL" --fail-on 'score<90,severity>=error'
  variables:
    AUDIT_URL: "https://staging.example.com"
    SQUIRRELSCAN_API_KEY: $SQUIRRELSCAN_API_KEY   # optional, set in CI/CD variables

Generic runners

Any runner that can run a shell works:

curl -fsSL --connect-timeout 10 --max-time 120 https://install.squirrelscan.com | bash
export PATH="$HOME/.local/bin:$PATH"

# JSON report on stdout stays clean — the gate summary goes to stderr.
squirrel audit https://example.com \
  --format json --output report.json \
  --fail-on 'score<90,score:perf<80'

The command exits 2 if a threshold trips, so the script stops there.

Authentication

Cloud features require a token. The recommended approach is an API key (mint one with squirrel keys create) stored as a CI secret and exposed as SQUIRRELSCAN_API_KEY:

  • GitHub Actions: repo/org secret → env: SQUIRRELSCAN_API_KEY: ${{ secrets.SQUIRRELSCAN_API_KEY }}
  • GitLab: masked CI/CD variable SQUIRRELSCAN_API_KEY
  • Other: export SQUIRRELSCAN_API_KEY in the job environment

When SQUIRRELSCAN_API_KEY is set, the CLI uses it automatically (the older SQUIRREL_API_TOKEN name still works as a back-compat alias). Without either, the audit still runs deterministically; it just skips cloud enrichment.

What an API-key audit costs

An audit signed in with an org API key is not registered as a cloud run, so it is billed differently from a squirrel auth login audit:

  • No audit or page charge. It pays no 50-credit audit base and no per-page charge.
  • Links checked on the runner, free. Its external links are always checked from the CI machine, never by the cloud’s link checker, and cost nothing. Expect more false positives from sites that block automated traffic.
  • Cloud renders are billed. A page it renders in the cloud is billed as a standalone render, 2 credits per page. An HTTP-only audit (--http) renders nothing.

This is deliberate. A CI audit gates a build, and the full billed audit is a signed-in squirrel audit or a cloud audit. See Credits and pricing.

Type to search…

↑↓ navigate↵ openesc close