Scan-Engines
AllyProof nutzt drei Engines parallel, um die Erkennungsabdeckung zu maximieren. Die primäre Engine (axe-core) verfolgt eine Zero-False-Positive-Richtlinie. Kombinierte Abdeckung: ~70 % der automatisierbaren WCAG-Probleme als deterministische Verstöße, plus eine eigene Advisory-Spur für WCAG-Kriterien, die nur teilweise automatisiert werden können und eine menschliche Prüfung benötigen.
Engine-Pipeline

Barrierefreiheits-Analysepipeline: eine mehrschichtige Scan-Architektur, die deterministische, beratende, Vorschau- und KI-gestützte Ergebnisse erzeugt. Engine 1, axe-core, erzeugt deterministische Verstöße ohne Falsch-Positive – dies ist die primäre Engine. Engine 2, HTML_CodeSniffer, erzeugt zusätzliche Verstöße aus Fehlern und Warnungen. Ergebnisse werden nach Element-Fingerabdruck kombiniert mit WCAG-Kriterium dedupliziert, und eine statische Techniküberschneidungs-Karte verwirft Techniken wie H37, G18 und H44, bei denen axe-core denselben Fehler bereits markiert hat. Engine 2b, HTMLCS-Hinweise, sind beratende Einträge zur manuellen Prüfung mit is_advisory auf true gesetzt. Sie werden mit einer Manuelle-Prüfung-Kennzeichnung angezeigt und niemals in Score, VPAT, Zertifikaten oder öffentlichen Berichten gezählt. Engine 3, APCA, ist eine WCAG-3.0-Vorschau-Kontrastprüfung – nur informativ, neben WCAG 2.x angezeigt, aber niemals zur Konformitätsprüfung verwendet. Engine 4, KI-Analyse, läuft nach dem Scan, ist auf Agency und Enterprise beschränkt und wird asynchron als Ebene 4 ausgeführt. Sie zielt auf Kriterien ab, die menschliches Urteilsvermögen erfordern: WCAG 1.4.1 nur Farbe, 3.3.2 Formatanweisungen und 3.2.3 seitenübergreifende Navigationskonsistenz. Sie erstellt beratende Einträge mit dem Präfix ai- bei rule_id, jeweils mit Vertrauenskennzeichnung. Deterministische Befunde aus den Engines 1 und 2 fließen in den Kern-Score ein. Beratende und Vorschau-Ebenen werden separat angezeigt.
Pipeline als strukturierten Text lesen
- Engine 1 — axe-coreDeterministisch
Deterministische Verstöße mit einer Garantie für null Falsch-Positive.
- Engine 2 — HTML_CodeSnifferDeterministisch
Fehler und Warnungen zeigen zusätzliche Verstöße auf. Ergebnisse werden nach Element-Fingerabdruck × WCAG-Kriterium dedupliziert, und eine statische Techniküberschneidungs-Karte verwirft Techniken wie
H37,G18undH44, bei denen axe-core denselben Fehler bereits markiert hat. - Engine 2b — HTMLCS-HinweiseBeratend
Einträge mit
is_advisory = true, angezeigt mit einer „Manuelle Prüfung“-Kennzeichnung in der Problemliste. Werden niemals in Score, VPAT, Zertifikaten oder öffentlichen Berichten gezählt. - Engine 3 — APCAInformativ
WCAG-3.0-Vorschau-Kontrast. Wird neben WCAG 2.x angezeigt, niemals zur Konformitätsprüfung verwendet.
- Engine 4 — KI-Analyse (Ebene 4)Beratend
Nach dem Scan, stufenabhängig (Agency und Enterprise). Gezielte LLM-Prüfungen zu WCAG 1.4.1 (Farbe allein), 3.3.2 (Formatanweisungen) und 3.2.3 (seitenübergreifende Nav-Konsistenz). Erstellt beratende Einträge mit
rule_id = ai-*und einer Vertrauenskennzeichnung.
Warum vier Spuren statt einer kombinierten Liste
- Deterministische Verstöße (axe + HTMLCS-Fehler/-Warnungen) fließen in Scores, VPATs, Zertifikate und öffentliche geteilte Berichte ein. Zero False Positives ist die Garantie – alles, was hier auftaucht, lässt sich in einem Compliance-Gespräch verteidigen.
- Advisory-Elemente (HTMLCS-Hinweise) sind Prompts zur manuellen Prüfung für WCAG-Kriterien, die keine der beiden Engines vollständig automatisieren kann –
1.4.1(Farbe allein),3.3.2(Formularanweisungen),2.1.1/2.4.7(Fokusverhalten bei Modals, Karussells),1.2.x(Medienalternativen). Diese wurden früher verworfen; ihre Beibehaltung schließt den Großteil der Lücke bei der manuellen Prüfung ohne zusätzliche Laufzeitkosten. - APCA ist eine informative Vorschau des WCAG-3.0-Kontrastalgorithmus – wird neben WCAG-2.x-Ergebnissen angezeigt, aber nie zur Konformitätsprüfung herangezogen.
- KI-Analyse (Layer 4) führt drei gezielte LLM-Prüfungen für Kriterien durch, bei denen Urteilsvermögen wichtiger ist als Regelabgleich. Nur für die Stufen Agency und Enterprise. Befunde sind Advisory, mit Konfidenz-Label versehen und beeinflussen niemals Scores oder rechtliche Berichte.
Engine 1: axe-core (primär)
| Eigenschaft | Wert |
|---|---|
| Quelle | Deque Systems (Open Source) |
| Regeln | 91 aktiv + 5 experimentell |
| Standards | WCAG 2.0/2.1/2.2 A+AA, Best Practice |
| Falsch-Positive | Null (strikte Richtlinie) |
| Abdeckung | ~57 % der automatisierbaren WCAG-Probleme |
axe-core ist der Industriestandard. Es verfolgt eine Zero-False-Positive-Richtlinie – es bleibt lieber still, statt riskant etwas zu melden, das kein echter Verstoß ist. Das macht es zur vertrauenswürdigen Basis für alle AllyProof-Scans.
Aktivierte experimentelle Regeln
css-orientation-lock– WCAG 1.3.4 Ausrichtunglabel-content-name-mismatch– WCAG 2.5.3 Label im Namenp-as-heading– WCAG 1.3.1 Informationen und Beziehungentable-fake-caption– WCAG 1.3.1 Informationen und Beziehungentd-has-header– WCAG 1.3.1 Informationen und Beziehungen
Engine 2: HTML_CodeSniffer (sekundär)
| Eigenschaft | Wert |
|---|---|
| Quelle | Squiz Labs (Open Source) |
| Regeln | ~200 Regeln |
| Standards | WCAG 2.1 A, AA, AAA |
| Integration | Browser-Skript-Injektion |
| Falsch-Positive | Niedrig (Fehler), Mittel (Warnungen) |
HTML_CodeSniffer nutzt andere Erkennungsalgorithmen als axe-core und findet dadurch Probleme, die axes strikte Zero-False-Positive-Richtlinie überspringt. Regel-IDs tragen zur Quellenidentifikation das Präfix htmlcs-.
So funktioniert die Deduplizierung
Die Deduplizierung erfolgt in zwei Schichten, damit nie doppelt gezählt und nie stillschweigend ein legitimer Befund verworfen wird, wenn sich die beiden Engines im Detail uneinig sind, aber beim Element übereinstimmen.
Schicht 1 – Fingerabdruck pro (Element, Kriterium). Das outerHTML jedes Elements wird normalisiert (Kleinschreibung, Leerraum zusammengefasst, Kommentare entfernt, gekürzt) zu einem stabilen Fingerabdruck. Der Dedup-Schlüssel ist {fingerprint}|{wcag_criterion}. Ein HTMLCS-Befund wird nur verworfen, wenn axe für dasselbe Element einen Verstoß gegen dasselbe Erfolgskriterium gemeldet hat. Meldet axe button-name für eine Schaltfläche und HTMLCS Kontrast für dieselbe Schaltfläche, bleiben beide erhalten – es sind unterschiedliche Probleme.
Schicht 2 – statische Technik-Überlappungskarte. Eine fest codierte Menge von HTMLCS-Technik-Codes (H37, G18, H44, F77, …) listet Fälle, in denen axe eine eigene Regel hat, die die gesamte Fläche abdeckt. Diese HTMLCS-Befunde werden unabhängig vom Fingerabdruck verworfen – ein Sicherheitsnetz gegen Formatierungsunterschiede. Bewusst konservativ gestaltet: Erfasst HTMLCS Randfälle, die axe nicht abdeckt, bleibt der Code aus der Überlappungsliste heraus.
Nachrichtentypen → Kategorien
| HTMLCS-Typ | Kategorie | Flag | Gezählt? |
|---|---|---|---|
| Fehler (1) | Deterministischer Verstoß | impact=serious | Ja |
| Warnung (2) | Deterministischer Verstoß | impact=moderate | Ja |
| Hinweis (3) | Advisory / manuelle Prüfung | is_advisory=true | Nein – inline mit einem Manuelle-Prüfung-Badge angezeigt |
Advisory-Elemente (HTMLCS-Hinweise)
Hinweise wurden früher als "zu ausführlich" verworfen. Damit ging genau das Signal verloren, das für Kriterien nötig ist, die keine der beiden Engines vollständig automatisieren kann. Hinweise bleiben jetzt als Advisory-Elemente mit is_advisory=true erhalten:
| Eigenschaft | Advisory-Verhalten |
|---|---|
| In Verstoß-Summen gezählt | Nein |
| Beeinflusst Barrierefreiheits-Score | Nein |
| Erscheint in VPAT / Zertifikaten / öffentlichen Berichten | Nein |
| Fließt in KI-Fix-Vorschläge ein | Nein |
| In der Oberfläche angezeigt | Ja – inline in der Problemliste mit einem Manuelle Prüfung-Badge statt des Schweregrad-Badges. Die Detailseite öffnet sich mit einem gelben Hinweis, der erklärt, was manuelle Prüfung bedeutet. |
| Über Scans hinweg gespeichert | Ja, mit nach Kategorie getrennter Resolve-Nachverfolgung |
| Separat gezählt | Ja – advisory_count bei Scan-Jobs und Seiten-Scans |
Hinweise, deren Technik in der axe-Überlappungskarte steht, werden verworfen (kein Sinn in "bitte Alt-Text manuell prüfen", wenn axe bereits jedes Bild geprüft hat). Alles andere bleibt erhalten.
Engine 3: APCA-Kontrast (Vorschau)
| Eigenschaft | Wert |
|---|---|
| Quelle | Myndex / W3C-WCAG-3.0-Entwurf |
| Typ | Perzeptueller Kontrastrechner |
| Standard | WCAG 3.0 (Entwurf) |
| Falsch-Positive | Keine (mathematisch) |
WCAG 3.0 ersetzt die WCAG-2.x-Kontrastverhältnis-Formel durch APCA (Advanced Perceptual Contrast Algorithm). APCA berücksichtigt Schriftgröße, -stärke und perzeptuelle Gleichmäßigkeit und liefert dadurch genauere Lesbarkeitsprognosen.
APCA-Lc-Schwellenwerte
| Lc-Wert | Anwendungsfall |
|---|---|
| 90+ | Bevorzugt für Fließtext |
| 75 | Minimum für Fließtext (16px normal) |
| 60 | Minimum für großen/fetten Text |
| 45 | Minimum für Nicht-Text-UI-Elemente |
| 30 | Absolutes Minimum für jeglichen Text |
Engine 4: KI-Analyse (Layer 4 – Agency + Enterprise)
| Eigenschaft | Wert |
|---|---|
| Läuft | Asynchron nach Abschluss des deterministischen Scans |
| Stufenbeschränkung | Nur Agency und Enterprise |
| Modell | Pro-Stufe-Auswahl durch Superadmin (Anthropic / Google / OpenAI) |
| Kostenobergrenze | ~40.000 Tokens pro Scan, hart begrenzt |
| Ausgabe | Advisory-Elemente (is_advisory=true, Regel-ID-Präfix ai-) |
| Fließt in Scores / VPATs / Zertifikate ein | Nein |
Nach den Schichten 1–3 sind rund 30 % der WCAG-AA-Kriterien für statische Analyse weiterhin unerreichbar. Die meisten davon erfordern Urteilsvermögen – "wird die Bedeutung dieses roten Punkts anderswo vermittelt?", "sagt dieses Label dem Nutzer, das Datum als TT.MM. einzugeben?", "ist die Navigation auf jeder Seite gleich?" Ein LLM kann über DOM + Kontext auf eine Weise urteilen, wie es keine Regel-Engine kann.
Layer 4 ist bewusst eng gefasst. Es führt drei gezielte Prüfungen dort durch, wo die KI das höchste Signal-Rausch-Verhältnis hat – nicht jedes mögliche WCAG-Kriterium:
| Prüfung | Kriterium | Was die KI entscheidet |
|---|---|---|
| Farbe-allein-Indikator | 1.4.1 Verwendung von Farbe | Ist Farbe der einzige Hinweis, oder vermitteln auch Text/Icon/Form die Bedeutung? |
| Fehlende Formatanweisungen | 3.3.2 Beschriftungen oder Anweisungen | Kommuniziert ein formatpflichtiges Eingabefeld (Datum, Telefon, Code) das erwartete Format? |
| Navigationskonsistenz | 3.2.3 Konsistente Navigation | Stimmt die primäre Navigation über alle Seiten hinweg überein? (Nur KI kann seitenübergreifend vergleichen.) |
So funktioniert es
- Snippet-Erfassung während des Browser-Durchlaufs für jede Seite: bis zu 3 Navigationen, 20 Formularfelder (mit Labels + 300 Zeichen umgebendem Kontext + Pattern-/describedby-Flags) und 15 statusfarbige Elemente (gefiltert nach berechnetem Farbton). Jeder Bereich ist größenbegrenzt und wird in
page_scans.ai_snippetsgespeichert. - Stufenprüfung + Modellauswahl. Der Orchestrator prüft den Plan der Organisation gegen
aiScanAnalysisund liest das vom Superadmin konfigurierte Modell für den Scan-Analyse-Workload. - Seiten-Stichprobe. Bis zu 3 Seiten pro Scan – die Startseite wird immer einbezogen, falls vorhanden, plus die Seiten mit der interessantesten Snippet-Masse. Deterministisch, sodass Wiederholungen cache-freundlich sind.
- Gebündelte LLM-Aufrufe. Jede Prüfung sendet kompakte JSON-Payloads mit einem konservativen System-Prompt. Befunde werden defensiv geparst – fehlerhafte Ausgaben werden verworfen, statt die gesamte Prüfung zum Absturz zu bringen.
- Upsert als Advisory. Gültige Befunde werden auf
violationsmitis_advisory=true, Regel-ID-Präfixai-und einem Konfidenz-Label abgebildet. Sie erscheinen inline in der Problemliste mit demselben Manuelle Prüfung-Badge wie HTMLCS-Hinweise; die Detailseite öffnet sich mit einem gelben Hinweis, der KI-basierte Befunde erklärt.
Konservative Ausgabe-Richtlinie
- Farbe-allein: muss das Fehlen eines konkreten redundanten Hinweises belegen; im Zweifel "unklar".
- Formatanweisungen: Freitextfelder werden standardmäßig als "kein Format erforderlich" eingestuft – nur eindeutige Fehlstellen werden gemeldet.
- Navigationskonsistenz: Befunde mit geringer Konfidenz werden komplett verworfen – seitenübergreifende Diffs haben ein hohes Falsch-Positiv-Risiko.
Modellauswahl
Der Superadmin wählt das Modell pro Plan-Stufe im KI-Scan-Analyse-Panel, analog zum KI-Fix-Vorschläge-Panel. Typisches Setup: ein günstigeres Modell der Haiku-Klasse für die Scan-Analyse (läuft häufig), ein stärkeres Modell für Fix-Vorschläge (läuft seltener, tiefere Analyse). Verfügbare Anbieter: Anthropic (Claude), Google (Gemini), OpenAI (GPT).
Abdeckungsvergleich
| Engine / Schicht | Regeln | Stufe | Abdeckungsbeitrag |
|---|---|---|---|
| axe-core | 91 | Alle | 57 % deterministisch (Basis) |
| HTML_CodeSniffer (Fehler & Warnungen) | ~200 | Alle | +10–15 % deterministisch |
| HTML_CodeSniffer (Hinweise → Advisory) | dasselbe 200er-Regelwerk | Alle | Schließt ~60 % der Lücke bei manueller Prüfung |
| APCA | 1 (Kontrast) | Alle | WCAG-3.0-Vorschau |
| KI-Scan-Analyse (Layer 4) | 3 gezielte Prüfungen | Agency + Enterprise | Deckt 1.4.1 / 3.3.2 / 3.2.3 ab – die wirkungsstärksten Kriterien, die KI zuverlässig beurteilen kann |
| Kombiniert | ~290 + 3 KI | Stufenabhängig | ~70 % automatisierbar + KI-markiert + HTMLCS-markiert zur manuellen Prüfung für den Rest |
Sicherheitsmauer um die KI
Die KI-Schicht verarbeitet HTML, das von Drittanbieter-Websites extrahiert wurde. Dieses HTML ist nicht vertrauenswürdig – eine bösartige Website könnte versteckten Text einbetten, der das Modell anweist, Daten abzugreifen, Befunde falsch zu klassifizieren oder eine Antwort mit XSS auszugeben. Das LLM selbst hat nie direkten Zugriff auf unsere Umgebungsvariablen oder die Datenbank; die eigentliche Angriffsfläche ist (1) eine vergiftete Antwort, die Nutzer täuscht, (2) gespeichertes XSS in gerenderter KI-Ausgabe, (3) Erkundung nach Tools/Prompts, (4) Ressourcenerschöpfung durch aufgeblähte Ausgaben und (5) feindliche URLs in KI-Inhalten.
Physische Isolation – der ai-worker-Dienst
Jeder LLM-Aufruf in der Produktion verlässt die Hauptanwendung per HTTP an einen isolierten Nebendienst unter services/ai-worker/. Dieser Dienst besitzt ausschließlich die LLM-Anbieter-Schlüssel und ein per HMAC geteiltes Geheimnis. Er hat keinen Supabase-Client, keine Paddle-Schlüssel, keine Resend-Schlüssel, keine R2-Zugangsdaten, keine Dateisystem-Schreibzugriffe (Container läuft mit --read-only und --cap-drop=ALL) und keinen Zugriff auf andere Dienste. Er ist an das interne Docker-Netzwerk gebunden und niemals dem Internet ausgesetzt. Anfragen sind HMAC-SHA256-signiert mit einem 60-Sekunden-Replay-Fenster und einer 1-MB-Body-Obergrenze.
Die Hauptanwendung ruft den Worker über einen einzigen Engpass auf (src/lib/ai/worker-client.ts). Anbieter-SDK-Importe sind dynamisch und durch einen Nur-Entwicklung-Fallback abgesichert, der in der Produktion hart blockiert ist. Eine Kompromittierung des LLM-Pfads – Prompt-Injection, Supply-Chain-Angriff oder anderes – verbrennt daher Tokens, legt aber keine Nutzerdaten, keine Mandanten-Geheimnisse und keine Abrechnungsdaten offen.
Prompt-Ebenen-Mauer (Verteidigung in der Tiefe, innerhalb beider Prozesse)
| Schicht | Wo | Was sie tut |
|---|---|---|
| Eingabe-Sanitizer | Hauptanwendung | Entfernt <script>, <style>, <iframe>, Event-Handler, javascript:-/vbscript:-/data:text/html-URIs, Zero-Width- und Bidi-Zeichen, HTML-Kommentare, data-*-Attribute und bekannte Prompt-Injection-Marker, bevor ein DOM-Snippet einen Prompt berührt. Visuell versteckte Elemente werden geleert. |
| Prompt-Wrapper | Hauptanwendung | Aller nicht vertrauenswürdiger Inhalt steht zwischen UNTRUSTED_START-/UNTRUSTED_END-Markern mit einem expliziten Leitplanken-Absatz und einer wiederholten Erinnerung nach dem Block. System-Prompts beginnen mit einer gemeinsamen Sicherheits-Präambel, die Vertrauensebenen trennt und dem Modell verbietet, seinen System-Prompt, Tools oder die Umgebung offenzulegen. |
| Worker-Bereinigung | ai-worker | Letzte Chance, bevor eine Antwort die Grenze überschreitet. Entfernt Script-/Style-/Iframe-/Event-Handler-/gefährliche-URI-Inhalte aus Fließtext (erhält eingezäunte Codeblöcke), entfernt Unsichtbares, begrenzt die Antwort auf 16 KB. |
| Ausgabe-Validator | Hauptanwendung | Jede Antwort wird gegen ein striktes Zod-Schema geparst. Freitext wird bereinigt (HTML-Tags entfernt, unsichtbare Zeichen entfernt, Länge begrenzt). URLs müssen zu http(s) auflösen. Alles, was die Validierung nicht besteht, wird stillschweigend verworfen. |
| UI-Escaping | Hauptanwendung | KI-Ausgabe wird über React-Textknoten und eigene Code-Highlighter gerendert – kein dangerouslySetInnerHTML. Selbst wenn eine Bereinigung etwas übersehen hat, erhält der Browser escapten Text. |
Keine einzelne Schicht ist für sich allein eine Sicherheitsgrenze. Der Wert entsteht durch die Kombination aus einem physischen Isolationsperimeter mit mehreren Prompt-Ebenen-Stolperdrähten. Eine vergiftete Antwort, die die Bereinigung des Workers übersteht, muss immer noch die Zod-Validierung der Hauptanwendung passieren – und selbst dann würde sie nur einen Prozess erreichen, der nicht die Schlüssel besitzt, die ein Angreifer wollen würde. maxTokens ist pro Aufruf begrenzt, und Layer 4 erzwingt ein Budget von 40.000 Tokens pro Scan, das bei Erschöpfung vorzeitig endet.
Was auch mit Layer 4 manuell bleibt
Selbst mit Advisory-Elementen und KI-Analyse bleiben diese Kriterien für jeden statischen oder asynchronen Scanner unerreichbar – sie erfordern menschliches Testen oder Laufzeit-Sonden:
- 2.3.1 Fotosensitives Blitzen – erfordert Bildwiederholrate-Analyse (PEAT)
- 3.3.1 / 3.3.3 Timing der Fehleransage – nur zur Laufzeit, erfordert assistive Technologie
- 1.2.3 / 1.2.5 Qualität von Untertiteln / Audiodeskription – Vorhandensein ja, Korrektheit nein
- 2.1.1 / 2.4.3 Modal-Fokusfalle / Fokus-Rückkehr – Laufzeitverhalten, erfordert Playwright-Interaktionssonden (zukünftige Arbeit, ohne LLM skriptierbar)