feat(platzhalter): Aufloesung, Namensregeln und Shell-Maskierung #26

Merged
florian.wilde merged 1 commits from feat/12-platzhalter-namensregeln into main 2026-09-25 13:30:31 +00:00
Owner

Schließt #12.

Aus einer Vorlage wird hier der PowerShell-Befehl, den ein Techniker kopiert und auf einem Domänencontroller ausführt. Entsprechend dicht ist die Abdeckung: 810 Tests, und die Maskierung wird ausgeführt geprüft, nicht gelesen.

Was dazugekommen ist

  • Platzhalter aus Gerät, Lauf, Mitarbeiter und Abteilung, dazu die Variablen der Vorlage. Ein unbekannter bleibt sichtbar stehen — eine leere Stelle im Befehl fällt niemandem auf, {{tipfehler}} schon.
  • {{ou}} ist der Eltern-Container des DN, also genau der Pfad, den ein New-ADUser -Path braucht.
  • Namensregeln für upn, sam, mail und hostname mit Transliteration, {v}, {nnn} und {kundenkuerzel}; Kundenregeln überlagern die globalen feldweise.
  • Maskierung je Shell, Skript-Kopie je Abschnitt mit Kommentarzeilen und dem passenden Zeilenumbruch.
  • {{generiertes_passwort}}: 20 Zeichen, bei jeder Anzeige neu, nirgends gespeichert; im Druck [Passwort – nicht gespeichert].

Der Review — drei Blocker

Der schwerste war eine Codeausführung. PowerShell liest nicht nur " als Begrenzer einer Zeichenkette, sondern auch “, ” und „ (und ‘, ’, ‚, ‛ für einfache). Die Maskierung kannte nur das ASCII-Zeichen. Ein Abteilungsname, den jemand aus Word kopiert — Word wandelt ein getipptes " von selbst in “/” —, beendete damit die Zeichenkette, und alles danach war Code.

Gefunden hat es der Review nicht durch Lesen: er hat sich PowerShell 7 in einen Container geholt und die Markierungsdatei entstehen lassen. Der Test dagegen hatte sich still übersprungen, weil auf dieser Maschine kein pwsh liegt — dieselbe Falle, die tests/helpers/db.ts für die Datenbank längst zugemacht hat. Er nimmt jetzt selbst das Container-Abbild und bricht in CI ab, statt zu schweigen. Ich habe die Korrektur mit demselben Aufbau gegengeprüft: neun Angriffswerte, alle kommen unverändert an, nichts wird ausgeführt.

Zwei verschiedene Passwörter in einer Antwort. befehleDesLaufs hat jeden Schritt zweimal gefüllt — einmal für die Anzeige, einmal für das Skript. Der Techniker sieht Passwort X, kopiert das Skript mit Passwort Y, legt das Konto mit Y an und nennt dem Benutzer X. Weil nichts gespeichert wird, ist Y danach unwiederbringlich.

Eine Vorlagenvariable konnte jeden eingebauten Platzhalter überschreiben — auch {{techniker}} und {{datum}}, die einen Befehl unterschreiben, und {{kunde}}, das im Modus Intern ausdrücklich leer ist. Gesperrt sind jetzt genau fünf Namen; upn, sam und mail bleiben frei, weil eine Onboarding-Vorlage danach fragen können muss.

Dazu sieben weitere Befunde, alle behoben — darunter die tragende Annahme der ganzen Maskierung, die niemand geprüft hat: sie gilt nur, wenn der Platzhalter in der Vorlage in Anführungszeichen steht. Write-Host {{vorname}} wird jetzt abgewiesen statt gefüllt.

Und einer, der mir selbst gehört: $' ist in String.replaceAll ein Rückverweis — genau der Fehler, den der Review in #010 gefunden hatte und in den ich hier wieder getappt bin. Gefunden hat es mein eigener Test gegen echtes Bash.

Eine Entscheidung, die den Auftragstext korrigiert

Das Akzeptanzkriterium nennt jmuellerluedensch und setzt in Klammern „auf 20 Zeichen gekürzt“. Der Name hat 17 Zeichen. Beides zusammen geht nur mit zwei Regeln: der Bindestrich fällt im sam weg, und eine Regel ohne eigenen {nnn} hält drei Stellen für die spätere Unterscheidung frei. Der Vorrat wird immer zurückgehalten — sonst hieße derselbe Mensch jmuellerluedenscheid, solange er der Erste ist, und jmuellerluedensch2, sobald ein Zweiter dazukommt.

Offen geblieben

Cmd ist begründet, nicht gemessen — es gibt hier kein Windows. Die Ablehnung von ", CR, LF und Null-Byte und die Bewertung von % und ! stehen als Begründung im Code, mit dem ausdrücklichen Hinweis, was daran Annahme ist.

Prüfung

pnpm lint && pnpm typecheck && pnpm format:pruefen && pnpm test && pnpm pruefe:doku grün, 810 Tests und kein stiller Übersprung mehr.

🤖 Generated with Claude Code

Schließt #12. Aus einer Vorlage wird hier der PowerShell-Befehl, den ein Techniker kopiert und auf einem Domänencontroller ausführt. Entsprechend dicht ist die Abdeckung: **810 Tests**, und die Maskierung wird **ausgeführt** geprüft, nicht gelesen. ## Was dazugekommen ist - Platzhalter aus Gerät, Lauf, Mitarbeiter und Abteilung, dazu die Variablen der Vorlage. Ein unbekannter bleibt sichtbar stehen — eine leere Stelle im Befehl fällt niemandem auf, `{{tipfehler}}` schon. - `{{ou}}` ist der Eltern-Container des DN, also genau der Pfad, den ein `New-ADUser -Path` braucht. - Namensregeln für `upn`, `sam`, `mail` und `hostname` mit Transliteration, `{v}`, `{nnn}` und `{kundenkuerzel}`; Kundenregeln überlagern die globalen **feldweise**. - Maskierung je Shell, Skript-Kopie je Abschnitt mit Kommentarzeilen und dem passenden Zeilenumbruch. - `{{generiertes_passwort}}`: 20 Zeichen, bei jeder Anzeige neu, nirgends gespeichert; im Druck `[Passwort – nicht gespeichert]`. ## Der Review — drei Blocker **Der schwerste war eine Codeausführung.** PowerShell liest nicht nur `"` als Begrenzer einer Zeichenkette, sondern auch `“`, `”` und `„` (und `‘`, `’`, `‚`, `‛` für einfache). Die Maskierung kannte nur das ASCII-Zeichen. Ein Abteilungsname, den jemand aus Word kopiert — Word wandelt ein getipptes `"` von selbst in `“`/`”` —, beendete damit die Zeichenkette, und alles danach war Code. Gefunden hat es der Review nicht durch Lesen: er hat sich PowerShell 7 in einen Container geholt und die Markierungsdatei entstehen lassen. Der Test dagegen hatte sich **still übersprungen**, weil auf dieser Maschine kein `pwsh` liegt — dieselbe Falle, die `tests/helpers/db.ts` für die Datenbank längst zugemacht hat. Er nimmt jetzt selbst das Container-Abbild und bricht in CI ab, statt zu schweigen. Ich habe die Korrektur mit demselben Aufbau gegengeprüft: neun Angriffswerte, alle kommen unverändert an, nichts wird ausgeführt. **Zwei verschiedene Passwörter in einer Antwort.** `befehleDesLaufs` hat jeden Schritt zweimal gefüllt — einmal für die Anzeige, einmal für das Skript. Der Techniker sieht Passwort X, kopiert das Skript mit Passwort Y, legt das Konto mit Y an und nennt dem Benutzer X. Weil nichts gespeichert wird, ist Y danach unwiederbringlich. **Eine Vorlagenvariable konnte jeden eingebauten Platzhalter überschreiben** — auch `{{techniker}}` und `{{datum}}`, die einen Befehl unterschreiben, und `{{kunde}}`, das im Modus Intern ausdrücklich leer ist. Gesperrt sind jetzt genau fünf Namen; `upn`, `sam` und `mail` bleiben frei, weil eine Onboarding-Vorlage danach fragen können muss. Dazu sieben weitere Befunde, alle behoben — darunter die **tragende Annahme der ganzen Maskierung**, die niemand geprüft hat: sie gilt nur, wenn der Platzhalter in der Vorlage in Anführungszeichen steht. `Write-Host {{vorname}}` wird jetzt abgewiesen statt gefüllt. Und einer, der mir selbst gehört: `$'` ist in `String.replaceAll` ein Rückverweis — genau der Fehler, den der Review in #010 gefunden hatte und in den ich hier wieder getappt bin. Gefunden hat es mein eigener Test gegen echtes Bash. ## Eine Entscheidung, die den Auftragstext korrigiert Das Akzeptanzkriterium nennt `jmuellerluedensch` und setzt in Klammern „auf 20 Zeichen gekürzt“. Der Name hat **17** Zeichen. Beides zusammen geht nur mit zwei Regeln: der Bindestrich fällt im `sam` weg, und eine Regel ohne eigenen `{nnn}` hält drei Stellen für die spätere Unterscheidung frei. Der Vorrat wird immer zurückgehalten — sonst hieße derselbe Mensch `jmuellerluedenscheid`, solange er der Erste ist, und `jmuellerluedensch2`, sobald ein Zweiter dazukommt. ## Offen geblieben **Cmd ist begründet, nicht gemessen** — es gibt hier kein Windows. Die Ablehnung von `"`, CR, LF und Null-Byte und die Bewertung von `%` und `!` stehen als Begründung im Code, mit dem ausdrücklichen Hinweis, was daran Annahme ist. ## Prüfung `pnpm lint && pnpm typecheck && pnpm format:pruefen && pnpm test && pnpm pruefe:doku` grün, **810 Tests** und kein stiller Übersprung mehr. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
florian.wilde added 1 commit 2026-09-25 13:30:18 +00:00
feat(platzhalter): Aufloesung, Namensregeln und Shell-Maskierung
Prüfung / pruefung (pull_request) Canceled after 0s
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (pull_request) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
b59fbb4645
Aus einer Vorlage wird hier der PowerShell-Befehl, den ein Techniker kopiert und
auf einem Domaenencontroller ausfuehrt. Entsprechend dicht ist die Abdeckung:
810 Tests, und die Maskierung wird **ausgefuehrt** geprueft, nicht gelesen.

- Platzhalter aus Geraet, Lauf, Mitarbeiter und Abteilung, dazu die Variablen
  der Vorlage; ein unbekannter bleibt sichtbar stehen
- `{{ou}}` ist der Eltern-Container des DN — genau der Pfad fuer New-ADUser
- Namensregeln fuer upn, sam, mail und hostname mit Transliteration, `{v}`,
  `{nnn}` und `{kundenkuerzel}`; Kundenregeln ueberlagern die globalen feldweise
- Maskierung je Shell, Skript-Kopie je Abschnitt mit Kommentarzeilen
- `{{generiertes_passwort}}`: 20 Zeichen, bei jeder Anzeige neu, nirgends
  gespeichert; im Druck `[Passwort – nicht gespeichert]`

Der unabhaengige Review fand drei Blocker. Der schwerste war eine
Codeausfuehrung: PowerShell liest auch `“`, `”` und `„` als Begrenzer einer
Zeichenkette, die Maskierung kannte nur das ASCII-Zeichen. Ein Abteilungsname
aus Word — Word wandelt `"` von selbst um — reichte. Gefunden hat es der Review
nicht durch Lesen, sondern indem er sich PowerShell in einen Container geholt
und die Markierungsdatei hat entstehen lassen. Der Test dagegen hatte sich still
uebersprungen; er nimmt jetzt selbst das Abbild und bricht in CI ab.

Dazu: zwei verschiedene Passwoerter in einer Antwort (Anzeige und Skript wurden
getrennt gefuellt), eine Vorlagenvariable, die `{{techniker}}` und `{{kunde}}`
ueberschreiben konnte, und die tragende Annahme der Maskierung — dass der
Platzhalter in Anfuehrungszeichen steht —, die niemand geprueft hat.

Schliesst #012

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
florian.wilde merged commit eec5de404a into main 2026-09-25 13:30:31 +00:00
florian.wilde deleted branch feat/12-platzhalter-namensregeln 2026-09-25 13:30:31 +00:00
Sign in to join this conversation.