4.9 KiB
Repo-Audit
Datum: 2026-05-19 Scope: vollstaendiges Repo Status: solide mit Risiken
Kurzfazit
- Kritischste Themen: persistente HTML-/Script-Injection ueber
innerHTML, unsichere Markdown-Link-Behandlung, Funktionsabweichungen bei Reset und Task-Erzeugung
Reproduzierbarkeit
Vor dem Audit wurden die verfuegbaren automatisierten Checks ueber ./scripts/verify-repo.sh ausgefuehrt.
Findings
-
[High] Persistente HTML-/Script-Injection ueber unescaped User-State Datei:
index.html:1505-1513,index.html:1621-1627,index.html:2084-2120,index.html:2298-2313Problem: Mehrere Renderer schreiben benutzerkontrollierte Werte direkt perinnerHTMLins DOM, ohne sie vorher zu escapen, z. B.task.t,idea.text, Board-Namen und Gruppennamen. Diese Werte kommen aus Inputs,contenteditable,prompt()undlocalStorage. Warum es zaehlt: Ein Eintrag wie<img src=x onerror=...>wird persistent gespeichert und bei jedem Render erneut ausgefuehrt. Empfehlung: Alle benutzerkontrollierten Texte konsequent mitescapeHtml()behandeln oder DOM-Knoten pertextContent/createElementaufbauen statt HTML-Strings zu interpolieren. -
[High] Markdown-Renderer erlaubt
javascript:-Links Datei:index.html:1953-2017, insbesondereindex.html:2007Problem: Der Markdown-Parser escaped zwar HTML, uebernimmt aber Link-Ziele ungeprueft in<a href="$2" target="_blank">. Ein Markdown-Link wie[x](javascript:alert(1))bleibt klickbar. Warum es zaehlt: Jede geladene.md-Datei kann so aktiven Script-Code hinter einem scheinbar normalen Link verstecken. Empfehlung: Link-Protokolle whitelisten (http:,https:, ggf.file:) und alles andere verwerfen oder als reinen Text rendern. Zusaetzlichrel="noopener noreferrer"setzen. -
[High]
Resetsetzt nicht aufDEFAULTSzurueck, sondern nur die Spalten Datei:SPEC.md:112,index.html:1012-1023Problem: Laut Spec soll↺ Resetdas aktuelle Board aufDEFAULTSzuruecksetzen. Implementiert wird aber nurcols = deepClone(DEFAULTS[curId].cols). Name, Goal, WIP-Limit, Throughput, SLE, Focus undoverviewbleiben erhalten. Warum es zaehlt: Der sichtbare UX-Vertrag stimmt nicht mit dem Verhalten ueberein; ein Reset hinterlaesst versteckte Altzustaende. Empfehlung: Das gesamte Default-Board zurueckkopieren und danach nurgroup/color/ringausBOARD_METAwieder anwenden. -
[Medium] Aus Ideen erzeugte Tasks bekommen kein
movedAtDatei:SPEC.md:137-138,index.html:1343-1349,index.html:2252-2260Problem: Beim Droppen einer Idee auf ein Board oder beim Promote-Dialog wird nur{ t: idea.text }angelegt.movedAtfehlt, obwohl es laut Datenmodell Grundlage fuer Aging ist. Warum es zaehlt: Diese Tasks altern nie sichtbar und verfaelschen die Board-Signale gegenueber regulaer angelegten Karten. Empfehlung: Beim Erzeugen aus Ideen dieselbe Initialisierung wie inaddCard()verwenden, inklusivemovedAt = Date.now(). -
[Medium] "Maskierte" Secrets liegen im Klartext in
localStorageund im DOM Datei:SPEC.md:52,index.html:906-964,index.html:1740-1746Problem: Der Secrets-Bereich ist nur optisch maskiert. Die Werte werden vollstaendig inkanban_v2gespeichert und zusaetzlich alsdata-value/data-copyins DOM geschrieben. Warum es zaehlt: Bei XSS, gemeinsam genutztem Browser-Profil oder lokalem Zugriff sind die Daten sofort auslesbar; die UI suggeriert mehr Schutz als tatsaechlich vorhanden ist. Empfehlung: Keine echten Secrets in App-State speichern. Stattdessen nur Env-Referenzen/Keys-Namen anzeigen oder Secrets separat ausserhalb des Boards halten. -
[Medium] State-Laden ist unvalidiert und schluckt Fehler vollstaendig Datei:
index.html:855-856,index.html:863-864,index.html:905-939,index.html:2202-2203Problem:localStorage-Payloads werden ohne Shape-Validierung uebernommen, und Exceptions werden mit leerencatch {}/catch(e) {}verschluckt. Schon eine kaputte Struktur kann das Laden teilweise abbrechen, ohne Hinweis fuer den Nutzer. Warum es zaehlt: Beschaedigter oder zukuenftiger inkompatibler State fuehrt zu stillen Datenverlusten oder schwer erklaerbaren Resets. Empfehlung: Geladene Daten vor der Uebernahme validieren, defekte Teile gezielt verwerfen und einen sichtbaren Recovery-Hinweis anzeigen.
Test- und Pruefstand
- Tests: nicht ausgefuehrt, kein Test-Setup im Repo vorhanden
- Lint/Typecheck/Build: nicht ausgefuehrt, kein entsprechendes Setup vorhanden
- Shell-Syntax:
bash -n server.sherfolgreich - Nicht verifiziert: echtes Browser-Laufzeitverhalten, Drag-and-drop im UI, Verhalten unter beschaedigtem
localStorage
Empfohlene Reihenfolge
- XSS-Pfade in Renderern schliessen
- Markdown-Link-Whitelist ergaenzen
resetCurrentBoard()auf echten Default-Reset umstellen- Task-Erzeugung vereinheitlichen (
addCard, Idea-Drop, Promote) - Secrets-Handling entschaerfen
localStorage-Load validieren und Fehler sichtbar machen