axe-rules — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited axe-rules (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Canonical source:examples/AXE_RULES_REFERENCE.mdinmgifford/ACCESSIBILITY.mdThis skill is derived from that file. When in doubt, the example is authoritative.
Apply these rules when writing, reviewing, or debugging axe-core scans.
Axe-core catches ~30–40 % of WCAG issues automatically. It is the baseline, not the ceiling. Always pair automated scanning with manual keyboard and screen reader testing.
Key tags to include in scans:
.withTags(['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa'])| axe severity | Meaning |
|---|---|
| critical | Blocks access for one or more disability groups |
| serious | Significantly impairs access |
| moderate | Creates friction; workaround exists |
| minor | Best-practice gap; marginal impact |
| Rule ID | Category | Description |
|---|---|---|
image-alt | Text alternatives | <img> missing alt attribute |
input-image-alt | Text alternatives | <input type="image"> missing alt |
video-caption | Text alternatives | <video> without captions |
aria-allowed-attr | ARIA | Element has unsupported ARIA attributes for its role |
aria-hidden-body | ARIA | aria-hidden applied to <body> |
aria-required-attr | ARIA | Required ARIA attribute missing |
aria-required-children | ARIA | Required child ARIA roles missing |
aria-required-parent | ARIA | Required parent ARIA role missing |
aria-roles | ARIA | Invalid ARIA role value |
aria-valid-attr | ARIA | Invalid ARIA attribute name |
aria-valid-attr-value | ARIA | ARIA attribute has invalid value |
label | Forms | Form input without associated <label> |
select-name | Forms | <select> without accessible name |
button-name | Buttons/Links | Button without discernible text |
input-button-name | Buttons/Links | <input type="button"> without text |
duplicate-id-aria | Structure | Duplicate id values referenced by ARIA |
meta-refresh | Meta | <meta http-equiv="refresh"> causes timed redirect |
| Rule ID | Category | Description |
|---|---|---|
object-alt | Text alternatives | <object> without accessible text |
svg-img-alt | Text alternatives | SVG with role="img" and no accessible name |
aria-braille-equivalent | ARIA | Braille label without non-braille equivalent |
aria-command-name | ARIA | Button or link without accessible name |
aria-hidden-focus | ARIA | aria-hidden element contains focusable content |
aria-input-field-name | ARIA | ARIA input field without accessible name |
aria-prohibited-attr | ARIA | Prohibited ARIA attribute used |
color-contrast | Color | Text contrast below 4.5:1 (normal) or 3:1 (large) |
frame-title | Frames | <iframe> without accessible name |
html-has-lang | Language | <html> missing lang attribute |
html-lang-valid | Language | lang attribute has invalid BCP 47 value |
valid-lang | Language | Inline lang value is invalid |
document-title | Language | <title> element missing |
list | Structure | <ul>/<ol> contains elements other than <li> |
listitem | Structure | <li> outside <ul> or <ol> |
definition-list | Structure | <dl> contains elements other than <dt>/<dd> |
dlitem | Structure | <dt>/<dd> outside <dl> |
bypass | Keyboard | No skip navigation mechanism present |
scrollable-region-focusable | Keyboard | Scrollable region not keyboard accessible |
link-name | Buttons/Links | Link without discernible text |
link-in-text-block | Buttons/Links | Link not distinguishable from surrounding text |
avoid-inline-spacing | Content sizing | Text spacing overrides not adjustable |
autocomplete-valid | Forms | autocomplete attribute invalid or missing |
tabindex | Best practices | tabindex value > 0 used |
label-title-only | Best practices | Form field labeled only via title attribute |
| Rule ID | Category | Description |
|---|---|---|
heading-order | Headings | Heading levels skipped (e.g., h1 → h3) |
th-has-data-cells | Tables | Table headers have no associated data cells |
td-headers-attr | Tables | Table cells reference invalid header IDs |
table-duplicate-name | Tables | <caption> text duplicates summary attribute |
meta-viewport | Meta | Viewport user-scalable=no disables zoom |
html-xml-lang-mismatch | Language | lang and xml:lang attributes disagree |
form-field-multiple-labels | Forms | Form field has multiple conflicting labels |
landmark-one-main | Best practices | Page has no <main> landmark |
region | Best practices | Content exists outside landmark regions |
page-has-heading-one | Best practices | Page has no <h1> |
scope-attr-valid | Best practices | scope attribute has invalid value |
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('No WCAG 2.x AA violations', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa'])
.analyze();
expect(results.violations).toEqual([]);
});Common configuration options:
// Exclude a specific element (use sparingly — document the reason)
.exclude('#known-false-positive')
// Include only a specific element
.include('#component-under-test')
// Disable a specific rule (document the reason and JIRA/issue link)
.disableRules(['color-contrast'])wcag2a, wcag2aa, wcag21aa, wcag22aa tagsAutomation covers ~30–40 % of WCAG issues. Always pair with manual testing.
Standards horizon: These rules target WCAG 2.2 AA. Monitor: <https://www.w3.org/TR/wcag-3.0/>
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.