Skip to content
All integrationsIntegrations · GitHub

Catch ADA & EAA risk on every pull request.

The Action runs a full WCAG 2.2 AA audit inside your own runner — your app is built and rendered in a real browser, no public URL, no crawler, nothing leaves your CI. New violations get posted directly on the PR, with plain-English fixes telling you which file, line and attribute to change.

Setup

Six steps, four minutes.

  1. Create an API key from the API keys page in your ScanAccess dashboard. Keys are prefixed sa_live_ (production) or sa_test_ (sandbox).

  2. Store the key as SCAN_ACCESS_API_KEY in your repository's GitHub Secrets (Settings → Secrets and variables → Actions). Keys are shown once at creation.

  3. Make sure your project has a build step (npm run build) that outputs a static bundle, and that npx serve can serve it on a local port.

  4. Keep the rendering engine pinned to the version shown in the snippet — using another version triggers a runtime error.

  5. Copy this workflow into .github/workflows/a11y.yml. Set your app routes under routes: (one per line). Adjust fail-on if needed (never|minor|moderate|serious|critical|any — default: critical).

  6. Open a pull request. The Action runs, posts findings as a PR check, and uploads a SARIF file to the Security tab of your repository.

Workflow

Copy-paste as is.

.github/workflows/a11y.yml
name: Accessibility audit
on:
  pull_request:
permissions:
  contents: read
  pull-requests: write
  security-events: write
jobs:
  a11y:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
      - run: npm ci
      - run: npm run build
      - run: npx serve -l 4173 ./dist &
      - uses: actions/cache@v4
        with:
          path: ~/.cache/ms-playwright
          key: playwright-chromium-1.60.0
      - run: npx playwright@1.60.0 install --with-deps chromium
      - uses: ghostdog-dev/scan-access-action@v2
        id: a11y
        with:
          api-key: ${{ secrets.SCAN_ACCESS_API_KEY }}
          app-url: http://localhost:4173
          routes: |
            /
            /pricing
            /about
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: ${{ steps.a11y.outputs.sarif-file }}

Important notes

  • Pin Playwright to 1.60.0

    Do not change the Playwright version. The Action bundles a Chromium binary compiled for 1.60.0. Any mismatch causes an “Executable doesn't exist” error that will fail your workflow silently until the cache is cleared.

  • Self-host fonts and CSS

    Playwright runs in a sandboxed runner. External CDN resources (Google Fonts, Tailwind CDN) may be blocked or timeout. Bundle or inline all assets in your build output before serving.

  • Required permissions

    The workflow needs contents: read, pull-requests: write (to post the PR check), and security-events: write (to upload the SARIF file). Without these, the Action will fail with a 403 on the SARIF upload step.

  • Don't override the browser cache path

    Setting PLAYWRIGHT_BROWSERS_PATH overrides the default cache location and breaks the cache/restore step. Use the cache path ~/.cache/ms-playwright as shown in the snippet.

Use cases

Ship fast without shipping a lawsuit.

  • Shopify theme / Remix app

    Block contrast and alt-text regressions before they reach merchants — and see which third-party app (Klaviyo, Yotpo, Privy) introduced each one.

  • Next.js / Astro / Vite SaaS

    Runs on every preview deploy. Your app is built and rendered inside the runner — no public URL needed. Every route audited against WCAG 2.2 AA before merge.

  • Digital agency (multi-client)

    One workflow per client repo, all keyed to one agency account. The Agency plan covers 1,000 CI scans/month across up to 50 monitored sites — white-label reports included.

FAQ

Common setup questions.

How do I get an API key?

Sign in to your ScanAccess dashboard, go to Settings → API keys, and create a key. Store it as SCAN_ACCESS_API_KEY in your repo's GitHub Secrets. Keys use a sa_live_ prefix for production and sa_test_ for sandbox.

Does it need a public URL or egress access?

No. The Action builds your app and serves it locally inside the GitHub runner. Each route is rendered in a real browser on the runner — nothing leaves your CI. No firewall rules or egress IPs needed.

Why does the rendering engine version have to match the snippet?

The Action ships with a browser binary built for the version shown in the snippet. Using a different version triggers a runtime error. Keep the version exactly as shown in the snippet and the cache step that goes with it.

What are the scan limits?

Each CI scan covers up to 30 routes. For apps with more routes, scan your most critical routes — or open a support ticket for higher limits.

Can it fail my build?

Yes — the fail-on input accepts never | minor | moderate | serious | critical | any. Default is critical. Use never for advisory mode and act on findings in a downstream job via the action outputs.

Why does my app show broken fonts or styles?

Self-host your fonts and CSS — do not rely on CDN URLs in your test build. The audit runs in a sandboxed runner; external resources may be blocked or slow. Inline or bundle all assets before serving.

Is the result the same as a manual scan?

Identical — same audit engine, same WCAG 2.2 AA scoring, same findings. The timestamped, hash-verified Defense PDF your lawyer can ask for is generated from the same scan in your dashboard.

Does this make my site ADA or EAA compliant?

No tool can promise that — and any that does is exposing you (the FTC fined an overlay vendor $1M in Jan 2025 for exactly that claim). Automated audits catch ~25–57% of issues. What this Action gives you is documented, timestamped proof of good-faith effort on every release — what courts actually look at.

Ship accessible PRs — and prove it.

Create an API key and add the workflow. Scanner starts at $29/mo for 40 scans / month.