Co zbývá pokazit

Na tomto webu není /admin. Žádný přihlašovací formulář, na kterém by šlo zkoušet hesla, žádná relační cookie, kterou by šlo ukrást, žádný seznam pluginů, který by bylo nutné porovnávat s CVE z minulého měsíce – ne proto, že by je někdo podle kontrolního seznamu odstranil, ale proto, že nic z toho nikdy nevzniklo.

Architektonické poznámky enginu říkají zbytek bez obalu: model hrozeb je statický web bez vlastního serveru. Nic tu neposlouchá na žádném portu. Cílem nikdy nebylo zabezpečit složitý systém proti všemu, co se v něm může pokazit. Cílem bylo žádný takový systém nepotřebovat.

Seznam toho, co zbývá pokazit, je pak kratší než u běžného blogu – co nesou stránky, co leží v pracovním adresáři, a ta jediná věc, která vstupuje zvenčí.

Jediná věc, která vstupuje zvenčí

Psaní z telefonu znamená, že jedny dveře přece jen přijímají bajty z cizího zařízení: scripts/receive.sh, spuštěný jako vynucený příkaz SSH klíče. Neposlouchá nikde – žádný socket, žádný démon, jen klíč, který smí spustit přesně tento skript a nic jiného.

Dovnitř vstupuje jméno souboru a proud bajtů.

Jméno souboru musí projít krátkým seznamem zákazů: žádná cesta, žádná tečka na začátku, žádný řídicí znak.

Proud je omezený dřív, než se cokoli uloží – BLOGSH_MAX_MB ukončí čtení jako první, takže nic v navazujícím zpracování nemůže přetéct jen tím, že je velké.

A Markdown, který následuje, se zpracuje v režimu confined: odkaz na obrázek smí být jen holé jméno souboru, protože cesta jako /etc/passwd napsaná do ![]() by se jinak načetla rovnou do příspěvku a zveřejnila jako fotografie.

Na té cestě není záměrně žádný archivní formát. Nic tu nikdy nerozbaluje, co poslal cizí člověk – a proto tu není nic, co by šlo napadnout technikou zip-slip.

Co lze stránku přimět zobrazit

Každý text přijatý ze sítě – zobrazované jméno z Fediverse, adresa avataru, text odpovědi – se escapuje dvakrát a pokaždé stejně: jednou, když sestavení zapisuje HTML, podruhé v DOM, který prohlížeč návštěvníka staví za běhu pro komentáře. Jedinou výjimkou je HTML stavů z Mastodonu; důvěřuje se mu proto, že ho Mastodon sanitizoval ještě před odesláním – důvěra patří tomu procesu, ne obsahu samotnému. Co všechno smí prohlížeč spustit nad rámec toho, vyjmenovává Content-Security-Policy dodaná jako meta tag – prostý statický hosting totiž nemusí dovolit nastavit hlavičku vůbec – a původ poskytovatele médií se povoluje jen na stránkách, které ho skutečně vkládají; archivní stránka bez vloženého obsahu nepovoluje nic.

Meze vyslovené, ne naznačené

Adresa náhledu konceptu nese náhodný token a noindex – je dost dlouhá, aby na ni nikdo nenarazil náhodou, a navíc je skrytá před vyhledáváním. Je to utajení, ne zámek. Koncept si přečte každý, ke komu odkaz dorazí – což je celý smysl toho, že se odkaz dá někomu poslat – a tak stojí za to nazvat to pravým jménem místo toho, aby se to vydávalo za řízení přístupu, kterým nikdy být nemělo.

env.sh drží skutečné přihlašovací údaje, do gitu se nedostane a zapisuje se s právy 600. Jedno místo, kde to tiše selhává: průvodci nastavením po sobě nechávají .bak toho, co přepsali, se stejnými právy a s tokeny, které platily předtím. Smazat ho stojí za to, jakmile se potvrdí, že nový token opravdu platí – zapomenutý .bak je druhá, nehlídaná kopie tajemství, o kterém sis myslel, že jsi ho vyřadil.

A pod obojím leží jedna věc, proti které tento model nechrání vůbec: stroj, na kterém sestavení skutečně běží. Napadený notebook nebo napadený server už vyhrál – stejně jako by vyhrál nad jakýmkoli nástrojem spuštěným z vlastního shellu toho stroje. Neexistuje tu scénář, ve kterém by sestavení chránilo před vlastním provozovatelem, a nic tu nepředstírá opak.

Nic z toho nepůsobí jako kontrolní seznam přišroubovaný dodatečně. Působí to jako zbytek, který zůstane, když se přihlášení, seznam pluginů a koncový bod pro nahrávání, co přijme cokoli, nikdy nedostaly na seznam.