GitHub Accessibility Scanner Integration
The GitHub Accessibility Scanner is a GitHub Action that scans web pages, files accessibility findings as GitHub issues, and can optionally assign those issues to GitHub Copilot.
The scanner is in public preview. Its inputs, permissions, issue lifecycle, scan engines, Copilot integration, and storage behavior can change. Pin a reviewed commit, record the review date, and recheck the upstream documentation before every update.
The scanner can provide useful automated evidence. It cannot establish WCAG conformance, determine the quality of every alternative, reproduce every user task, or guarantee that a proposed fix is accessible.
Recommended Use in This Project
Use the scanner for detection and issue tracking. Keep remediation as a separate, human-triggered process:
- Run the scanner in dry-run mode and review its scope and output.
- Enable issue filing only after labels, ownership, grouping, and lifecycle behavior are agreed.
- Set
skip_copilot_assignment: "true"so the scanner does not independently assign issues to Copilot. - Have a human triage each finding and confirm the affected user task.
- When AI assistance is useful, manually run
AGENT_REMEDIATION_WORKFLOW.ymlwith the issue number. - Review and apply an acceptable patch through the repository’s normal branch and pull-request process.
- Retest the final result with applicable automated, manual, and assistive technology checks.
This separation prevents two agents from acting on the same issue and keeps issue content from automatically triggering a workflow that can modify the repository.
Decide Whether the Scanner Fits
Before adoption, confirm that the repository accepts these characteristics:
- The action requires a personal access token (PAT); the upstream documentation
says the default
GITHUB_TOKENcannot be used. - The documented PAT permissions are broad because the action can maintain a cache branch, file and update issues, and create Copilot remediation pull requests.
- The action stores finding state on an orphan
gh-cachebranch. - It can close issues when a finding is absent from a later scan and reopen closed issues when a finding returns.
- Screenshots, when enabled, are also stored through the cache mechanism.
- Authenticated scans can expose sensitive session state or page content if inputs, logs, issues, screenshots, or artifacts are mishandled.
- The action and its dependencies execute third-party code in the workflow.
- Preview behavior and interfaces may change without the stability expected of a mature production dependency.
If the required credential or mutation scope is not acceptable, use a read-only scanner that produces an artifact and let a separate reviewed process create issues.
Current Interface
The following inputs were verified in the upstream action.yml at commit
21949ebcfc3229fb9338799f85608c60683ac3f6 on 2026-07-19. This table is a
review record, not a substitute for checking the pinned action.
| Input | Purpose | Review notes |
|---|---|---|
urls |
Newline-delimited scan targets | Required unless url_configs is supplied |
url_configs |
Per-URL configuration and Axe exclusions | Exclusions require narrow justification and review |
repository |
Repository where issues and pull requests are managed | Confirm the target explicitly |
token |
PAT used by the action | A separate credential; workflow token permissions do not constrain it |
cache_key |
Path used for persisted finding state | Use a stable, unique value per scan surface |
base_url |
GitHub API URL | Required for applicable GitHub Enterprise Server configurations |
login_url, username, password |
Simple authenticated scan | Keep credentials in secrets, never literal workflow text |
auth_context |
Serialized authenticated browser state | Treat as a high-value secret |
skip_copilot_assignment |
Prevent Copilot assignment | Set to true for the review-only pattern in this guide |
include_screenshots |
Store and link screenshots | Default false; screenshots may contain sensitive information |
open_grouped_issues |
Create a tracking issue for related findings | Decide whether this improves or duplicates triage |
group_by |
Group by finding, rule, or rule and URL | Choose based on ownership and remediation workflow |
file_best_practice_issues |
File findings categorized as best practices | Consider disabling initially to reduce untriaged volume |
file_experimental_issues |
File findings categorized as experimental | Consider disabling until the team reviews stability |
reduced_motion |
Set the Playwright motion preference | One configured state does not cover every preference |
color_scheme |
Set the Playwright color scheme | Run separate configurations for materially different themes |
scans |
Choose Axe, AccessLint, or scanner plugins | Default is Axe; review every added engine and plugin |
dry_run |
Report proposed mutations without performing them | Use for initial configuration and material updates |
Input availability, defaults, and accepted values are version-sensitive.
Start with a Dry Run
Use a manual trigger first. The example below pins the scanner to the commit reviewed for this guide. Re-review and replace the SHA before adoption.
GitHub expression syntax is wrapped in a Jekyll raw block so the documentation site does not interpret it.
name: Accessibility Scanner Preview
on:
workflow_dispatch:
permissions:
contents: read
jobs:
preview:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Preview accessibility findings
# github/accessibility-scanner, reviewed 2026-07-19.
uses: github/accessibility-scanner@21949ebcfc3229fb9338799f85608c60683ac3f6
with:
urls: |
https://example.com/
repository: ${{ github.repository }}
token: ${{ secrets.ACCESSIBILITY_SCANNER_TOKEN }}
cache_key: scanner-cache/example.com.json
dry_run: "true"
skip_copilot_assignment: "true"
include_screenshots: "false"
file_best_practice_issues: "false"
file_experimental_issues: "false"
color_scheme: light
reduced_motion: reduce
Replace https://example.com/ and the cache key. Do not enable the example
until the target, secret, action commit, and organization policy have been
reviewed.
In the pinned version, dry-run mode does not open, close, reopen, or assign issues and does not write the cache. It still runs the scanner and can place finding details in workflow logs. Review log visibility and retention before scanning private or authenticated content.
Token and Permission Model
Two permission systems are involved:
- The workflow’s
permissions:block controls the automatically generatedGITHUB_TOKEN. ACCESSIBILITY_SCANNER_TOKENis a separate PAT passed directly to the action.
Setting contents: read for GITHUB_TOKEN does not reduce the PAT’s authority.
The action can perform every operation granted to that PAT within its repository
scope.
At the time of review, the scanner README documented a fine-grained PAT with:
- Actions: write
- Contents: write
- Issues: write
- Pull requests: write
- Metadata: read
- access limited to the workflow repository and target repository
The upstream action.yml describes contents, issues, and pull-request write
access, while the README additionally lists Actions write. Treat the difference
as a reason to verify the exact pinned version rather than guessing.
Use these safeguards:
- Create a dedicated fine-grained PAT for the scanner.
- Limit it to the smallest possible repository set.
- Do not reuse a personal token with organization-wide access.
- Store it as an Actions secret; never commit it or echo it.
- Set an owner, purpose, expiry or rotation date, and revocation procedure.
- Test whether the selected pinned configuration works with narrower permissions. Record the result rather than assuming.
- If the action will not work with permissions the organization accepts, do not enable mutation mode.
- Review organization and enterprise policies that may override repository settings.
Move from Preview to Issue Filing
After reviewing dry-run output:
- Define the scan inventory and expected coverage.
- Decide which findings create issues.
- Select grouping that matches ownership.
- Define labels, severity triage, and response ownership.
- Review cache and issue lifecycle behavior.
- Keep Copilot assignment disabled for this project’s separate remediation workflow.
- Change
dry_runto"false"in a test repository or branch. - Inspect created, updated, closed, and reopened issues.
- Confirm no sensitive data appears in issues, logs, cache content, or screenshots.
- Add a schedule only after the first mutation run behaves as expected.
Do not automatically assign project severity from an Axe, AccessLint, or scanner category. Use the taxonomy in Accessibility Bug Reporting and evaluate the actual user task and impact.
Scan Scope and Coverage
Create a machine-readable or reviewed inventory containing:
- canonical URL;
- page or template owner;
- public and authenticated states;
- critical user tasks represented;
- theme, contrast, motion, viewport, locale, and permission variants;
- last successful scan date; and
- deliberate exclusions with owner and review date.
One run with color_scheme: light does not cover dark or system behavior. One
run with reduced_motion: reduce does not cover the default motion state. Use
separate jobs, matrices, or scheduled configurations when the rendered output
materially differs.
Keep the scan matrix proportionate. Fast browser checks can run on pull requests; deeper crawls and preference combinations can run on a schedule or before release.
URL authorization and boundaries
- Scan only sites and environments the project is authorized to test.
- Prefer staging or production-like test environments for authenticated scans.
- Do not send high request volumes to third-party services.
- Bound the URL list, runtime, and schedule.
- Review redirects so a trusted URL cannot silently move the scan to an unintended host.
- Do not place credentials in URLs.
- Treat content returned by scanned pages as untrusted.
Authenticated Scanning
The scanner supports simple username and password inputs and serialized authentication context. Authenticated state can contain cookies, tokens, personal information, account data, and confidential page content.
Before enabling it:
- use a dedicated least-privileged test account;
- keep passwords and authentication context in Actions secrets;
- prevent secrets from appearing in command output;
- review whether issue text or screenshots can expose protected content;
- disable screenshots unless they are required and safe;
- avoid production accounts with destructive permissions;
- define session expiry and credential rotation; and
- test logout, timeout, permission, and failure behavior separately where they affect user tasks.
Do not treat successful login as evidence that the authenticated task is accessible.
Finding and Issue Lifecycle
The scanner persists state on an orphan gh-cache branch. According to the
upstream FAQ, it uses that state to avoid duplicate issues, close issues when a
finding disappears, and reopen issues when the same finding returns.
Review these consequences:
- A finding can disappear because of a scan failure, changed scope, timing, authentication failure, selector exclusion, or tool update—not only because the barrier was fixed.
- Automatic closure is not verification that the user task now works.
- Resetting or deleting the cache can cause previously tracked findings to be filed or reopened.
- The upstream
wontfixlabel prevents some closed findings from reopening. Use a project-approved exception process rather than an unexplained label. - Cache content and screenshot storage require the same retention and privacy review as other test artifacts.
Require human review before treating automatic closure as remediation evidence. Link the final code change and manual verification to the issue where practical.
Grouping and Noise Management
The scanner can create one issue per finding, one per rule, or one per rule and URL. Choose based on how work is owned:
| Grouping | Advantage | Risk |
|---|---|---|
finding |
Precise reproduction and closure | High issue volume |
rule |
Lower volume and centralized rule discussion | Different components and owners become mixed |
rule+url |
Page-level ownership with some consolidation | Repeated template defects may remain fragmented |
Do not stop all scheduled scans merely because accessibility issues remain open. That can hide new regressions. Use the scanner’s cache, stable finding identity, grouping, triage queues, and response ownership to manage noise.
The best-practice and experimental categories are scanner metadata. They do
not decide WCAG conformance, user impact, or project severity. Review them
before enabling automatic issue creation.
Every exclusion should identify:
- the exact URL, selector, rule, engine, or state;
- why the result is not actionable;
- evidence supporting the decision;
- an owner and linked issue;
- an expiry or review date; and
- the narrowest possible scope.
Scanner Engines and Plugins
The reviewed version defaults to Axe and can opt into AccessLint or plugins
through scans.
Adding an engine or plugin changes coverage, dependencies, runtime, network behavior, findings, and possibly licensing. Before enabling one:
- verify the package, publisher, source, license, and maintenance status;
- pin the scanner and plugin version where supported;
- inspect installation scripts and transitive dependencies;
- compare duplicate and conflicting findings;
- document rules and known limitations; and
- repeat dry-run and mutation lifecycle testing.
Multiple engines can increase coverage, but duplicated findings without clear ownership can reduce the value of the system.
Copilot Options
There are two distinct patterns. Choose one deliberately.
Scanner-managed Copilot assignment
The scanner can assign findings to GitHub Copilot, which may propose pull requests. This is the upstream integrated model. It requires the applicable Copilot plan, repository configuration, and write-capable credential. Review current GitHub documentation and the scanner’s pinned implementation before using it.
Separate review-only remediation
This repository’s recommended model sets skip_copilot_assignment: "true" and
uses:
COPILOT_REMEDIATION_AGENT_PROMPT.mdfor the bounded task;AGENT_REMEDIATION_WORKFLOW.ymlto create an uncommitted patch and report artifact; and- human review, application, and retesting through the normal contribution workflow.
The reference remediation workflow does not commit, push, open or merge a pull request, close an issue, deploy, or modify repository settings.
Do not enable both remediation paths for the same findings without an explicit deduplication and ownership design.
Supply-Chain and Workflow Security
- Pin the scanner to a reviewed full commit SHA, not
@v3or@main. - Review the scanner’s composite action and all transitive action references.
- Recheck the SHA, source diff, release notes, inputs, and permissions before an update.
- Set explicit read-only
GITHUB_TOKENpermissions unless another workflow step requires more. - Remember that the separate PAT is not constrained by
permissions:. - Keep secrets unavailable to untrusted forked pull-request code.
- Avoid
pull_request_targetwhen untrusted code or configuration can execute. - Treat URLs, page content, scanner results, issue bodies, plugins, screenshots, and cached data as untrusted input.
- Add timeouts and concurrency controls.
- Review logs, issues, and the
gh-cachebranch for accidental secret or personal-data exposure. - Revoke the PAT immediately if exposure is suspected.
- Follow the scanner repository’s private security-reporting process for a suspected vulnerability; do not disclose it in a public issue.
Validation Checklist
Before enabling
- The scanner is still in a support state the project accepts.
- The exact action commit and transitive dependencies are reviewed.
- Scan targets and crawl boundaries are authorized.
- The PAT is dedicated, repository-scoped, stored as a secret, and owned.
- Required PAT permissions are verified against the pinned implementation.
GITHUB_TOKENpermissions are explicit.- Copilot assignment is intentionally enabled or disabled.
- Screenshots and authenticated scanning have a privacy review.
- Grouping, labels, owners, and issue lifecycle are defined.
- Best-practice and experimental findings are intentionally configured.
- Exclusions are narrow, documented, owned, and dated.
Dry run
- Expected URLs, states, themes, and preferences are reached.
- Login, redirects, timeouts, and failures behave safely.
- Logs contain no secrets or sensitive content.
- Findings are reproducible and useful to a reviewer.
- Missing coverage and false positives are documented.
Mutation test
- Issues are created and grouped as intended.
- Duplicate findings update existing state correctly.
- Resolved, absent, and recurring findings receive human review.
- Cache and screenshot content are acceptable.
- No unintended Copilot assignment or pull request occurs.
- Token audit logs and repository changes match expectations.
Ongoing operation
- Failed and skipped workflow runs are monitored.
- Action, browser, engine, rule, and configuration versions are recorded.
- Dependency updates repeat dry-run validation.
- PAT ownership, permissions, and rotation are reviewed.
- Open findings have owners and review dates.
- Automated closure is not treated as conclusive remediation evidence.
- Manual testing continues for requirements automation cannot evaluate.
Related Project Guidance
- CI/CD Accessibility Best Practices
- Shift-Left Accessibility Automation
- Accessibility Bug Reporting
- Manual Accessibility Testing
- Contributing Accessibility
- Copilot Agent Mode Guide
- Remediation Workflow
- Remediation Prompt
- Trusted Sources Registry
Primary References
- GitHub Accessibility Scanner README
- GitHub Accessibility Scanner action.yml
- GitHub Accessibility Scanner FAQ
- GitHub Accessibility Scanner Security Policy
- GitHub: Managing Fine-Grained Personal Access Tokens
- GitHub Actions Secure Use Reference
- GitHub: Script Injections
- WCAG 2.2
- WAI: Understanding ACT Rules
Version-sensitive claims and examples last reviewed: 2026-07-19.
This document is available under the repository’s MIT License.