Ich sehe das komplett umgekehrt. Bei Sachen wo man klar sagen kann, was
gültig ist und was nicht (z.B. eine Zahl sollte nur Ziffern haben), ist
Validierung und sanitizing der Daten OK und wichtig. Aber in allen
anderen Fällen (Name, Text, etc.) sollte man keine derartigen Änderungen
am Input vornehmen. Das ist unnötig und verärgert nur die Nutzer.
Wann auch immer es um Freiform Text geht, sollte man diesen Escapen, und
zwar ausschliesslich direkt vor / bei der Serialisierung. Man muss immer
damit rechen, dass variierende Daten schlecht sein können. Und sobald
man die Daten erstmal versehentlich dreifach mit Sanitizing und Escaping
ruiniert hat, bekommt man die nicht mehr ganz sauber / wie sie mal
waren. Darum, nur Escapen, aber genau da wo nötig.
Idealerweise macht man das aber gar nicht selbst. Bei vielen Templating
Engines wo man eine {variable} einfügt ist das Escapen der Default. (Bei
reinem PHP für templating leider nicht, da muss man selber
HTMLEntities() aufrufen, aber es gibt sicher gute PHP templating
Engines, die einem das abnehmen).
Noch besser sind dedizierte APIs. MySQL hat prepared statements, damit
sind Queries und unsichere Daten strikt getrennt, und man muss sich
selbst keine Gedanken mehr darüber machen.
Auf Browser / Client Seite, gibt es den DOM. Manchmal etwas verbose,
aber bei Sachen wie x.innerText=bla;
x.appendChild(document.createTextNode(bla)); usw. da kann nichts
unerwartetes passieren. Man kann auch ein Template nehmen, und dann per
DOM Instanzieren und Werte einfüllen. Reacts JSX ist da was dazwischen
Templating und DOM, auch ein nettes Konzept. Auch Serverseitig kann man
mit einem guten DOM auch dem Serializierer das escaping überlassen. Das
muss auch kein voller Browser DOM shim sein, ein simpler DOM mit
Elementen und Text Nodes reicht meisst schon. Wobei DOM Serialisierung
funktioniert besser bei XML als bei HTML.
HTML basiert auf SGML, und erfordert bei Serialisierung /
Deserialisierung dass diese jedes Element kennen, um korrekt zu
funktionieren. Das ist niemals der fall, denn es kommen auch immer
wieder neue dazu (wobei in der Regel zum glück keine self-closing tags,
vermutlich genau darum). Gewisse HTML Elemente sind self-closing, manche
können nur gewisse andere enthalten, etc. Und dann gibt es noch
sonderregeln bei Elementen wie <script>, <style> und <template>. In 99%
deer Fälle geht das trotzdem gut. Solange man Nutzer nur Texte &
bestimmte Attribute setzen lässt, ist das ok. Aber wenn man ihn tags /
HTML Dokumente erstellen lässt, muss man das einschränken, und man muss
höllisch aufpassen, was man durchgehen lässt. Damit meine ich nicht nur,
dass er keine <script> tags nutzen kann, das reicht nicht. Bei Browsern
z.B. gibt es Situationen, bei denen y.innerHTML=x.innerHTML NICHT zum
selben DOM Tree führen! (Was ich eigentlich auch falsch finde, aber es
gibt da wohl irgendwelche legacy gründe, warum man das nicht mehr ändern
kann). Wenn man also z.B. Formatierungen zulässt, am besten entweder
kein HTML zum speichern nehmen (eventuell stattdessen Markdown, oder ein
JSON oder so), oder notfalls ein XHTML Subset verwenden, wo nur wenige
Tags und Attribute gewhitelistet sind. Arbitrary HTML sanitization ist
eine der schwierigsten Sachen überhaupt, das kann man sonst eigentlich
nur verkacken, und sollte man deshalb vermeiden.
Und zuletzt noch zur Encoding. Das ist simpel. Immer überall konsistent
UTF-8 nehmen, dann ist alles gut. Aber nur dann.