HTML zapisuje obsah a štruktúru do rovnakého textového prúdu. Znak menší než môže byť súčasť matematickej vety, ale parser v ňom vidí možný začiatok tagu. Ampersand môže byť textom aj začiatkom character reference. Entity umožňujú autorovi povedať, že výsledkom má byť doslovný znak, nie nový markup. Nie sú šifrovaním ani všeobecným bezpečnostným filtrom; sú súčasťou gramatiky dokumentu.

Parser rozhoduje podľa kontextu

Medzi tagmi < vytvorí znak menší než a & ampersand. V quoted atribúte sú navyše významné úvodzovky. JavaScript, CSS a URL majú vlastné escaping pravidlá.

Jedna univerzálna funkcia preto nie je správna pre každý výstup. Encoder musí poznať cieľový kontext.

UTF-8 umožňuje väčšinu znakov zapísať priamo

Historicky entity pomáhali pri obmedzených charsetoch a klávesniciach. Moderný UTF-8 source môže obsahovať slovenskú diakritiku aj väčšinu symbolov bez entity.

References zostávajú nutné pre syntax-significant znaky a užitočné pre neviditeľné medzery. Konvertovať automaticky každý Unicode znak nezvyšuje bezpečnosť.

Encoding a sanitization nie sú to isté

Escaping zabezpečí, že text <strong> sa zobrazí a nevytvorí element. Sanitizer je potrebný, keď produkt zámerne povoľuje obmedzený rich text.

Sanitizer parsuje HTML a odstráni nepovolené tagy, atribúty a URL schemes. Regex alebo string replacement nedokáže modelovať tolerantný browser parser.

Double encoding prezrádza dvoch vlastníkov

Ak backend uloží encoded ampersand a template ho escapuje znovu, používateľ uvidí syntax entity. Databáza, API a renderer si nesmú všetky myslieť, že pripravujú HTML.

Obyčajný text sa ukladá sémanticky a escapuje až na poslednej hranici. Sanitizované HTML je samostatný typ.

Decode môže znovu vytvoriť markup

Dekódovanie je správne iba vtedy, keď input contract výslovne hovorí o HTML references. Na ľubovoľnom používateľskom texte môže zmeniť doslovnú sekvenciu na syntaktický znak.

Repeated decode je nebezpečný, pretože nested encoding môže postupne vytvoriť tag. Transformácia má byť jednorazová a dokumentovaná.

Unicode normalization rieši inú vrstvu

Priamy znak a entity môžu po parsovaní vytvoriť rovnaký code point. Dve vizuálne rovnaké Unicode hodnoty však môžu mať odlišnú kombináciu code points.

Search a unique identifiers môžu potrebovať NFC normalizáciu, no tá sa nemá miešať s HTML escapingom.

Browser je tolerantný k chybnému markup-u

Error recovery môže neúplnú referenciu alebo zle vnorený tag interpretovať prekvapivo. Jednoduchý filter môže vidieť inú štruktúru než browser.

Udržovaný encoder a sanitizer modelujú skutočné pravidlá. CSP pridáva ochranu, ale nenahrádza správny output context.

Template má bezpečnú cestu nastaviť ako default

Bežná interpolácia sa automaticky escapuje. Raw HTML vyžaduje explicitný helper a review. Výnimka má mať trusted source alebo sanitizer.

Ak kód najprv spojí untrusted text s markup stringom, neskorší encoder už hranicu neobnoví.

Source a DOM ukazujú dve fázy

Raw response ukáže, čo server odoslal. DOM ukáže, ako browser zdroj interpretoval. DevTools element inspector môže markup znovu serializovať a skryť pôvodnú podobu.

Regresný test kontroluje obe fázy, najmä ak klientský JavaScript hodnotu presúva alebo znovu parsuje.

Entities podporujú aj čitateľný zámer

Niektoré neviditeľné znaky je v source lepšie pomenovať referenciou, aby reviewer videl ich účel. Inde je priama Unicode podoba čitateľnejšia.

Cieľom nie je maximum entít, ale stabilná interpretácia a zrozumiteľný zdroj.

Entity je syntaktický nástroj

Nechráni súkromie a nepotvrdzuje dôveryhodnosť. Umožní bezpečne zapísať doslovný znak do konkrétneho HTML kontextu.

Praktické pravidlo je uchovať sémantický text, escapovať pri výstupe a sanitizovať iba zámerne povolený markup. Tým sa predíde artefaktom aj injection.

Textový a atribútový kontext sa nesmú zamieňať

V texte medzi elementmi sú kľúčové najmä ampersand a znak menší než. V quoted atribúte musí encoder bezpečne spracovať aj použitú úvodzovku. Unquoted atribút má ešte širšiu skupinu oddeľovačov a moderný template by sa mu pri dynamických hodnotách mal vyhnúť.

Bezpečne escapovaná atribútová hodnota stále nemusí byť bezpečnou URL, CSS alebo JavaScript hodnotou. Najprv sa overí význam vnútorného jazyka a až potom sa výsledok vloží do HTML atribútu. Každé vnorenie vytvára ďalšiu hranicu.

Named entity a numeric reference môžu mať rovnaký výsledok

&copy;, decimal reference a priamy UTF-8 znak môžu v DOM vytvoriť rovnaký code point. Aplikácia, ktorá porovnáva source stringy, však vidí tri odlišné zápisy. Po parsovaní treba pracovať s DOM textom, nie odhadovať sémantiku z pôvodnej entity syntaxe.

Nie všetky názvy bez semicolonu sú bezpečne jednoznačné. Browser error recovery obsahuje historické pravidlá. Producent má vždy emitovať kanonický zápis so semicolonom a nespoliehať sa na tolerantné správanie.

Sanitizer policy je produktová zmluva

Allowlist určuje, ktoré formátovanie používatelia môžu uložiť. Zmena policy môže odstrániť existujúci obsah alebo naopak povoliť nový atribút s bezpečnostným rizikom. Verzia sanitizeru a policy preto patria do migration plánu.

Pri oprave zraniteľnosti možno starý obsah re-sanitizovať. Systém potrebuje vedieť, ktoré záznamy vznikli starou verziou a či uchováva pôvodný source pre bezpečnú opätovnú transformáciu. Raw originál musí mať prísnejší prístup než publikovaná verzia.

Template kontrakt má rozlišovať trusted typ

Obyčajný string sa vždy escapuje. Iba objekt vytvorený schváleným sanitizerom alebo interným rendererom môže byť označený ako safe HTML. Taký typ zabráni náhodnému raw výstupu hodnoty z databázy.

Prevod zo stringu na trusted HTML je bezpečnostne citlivý constructor a má málo call sites. Code review potom nemusí analyzovať každú interpoláciu, ale sústredí sa na miesta, kde sa mení úroveň dôvery.