Jednorázový odkaz, který se zničí už při obyčejném GET, zanikne
ve chvíli, kdy ho Slack, Teams nebo brána e-mailu načtou kvůli náhledu.
Řešením je na GET vracet jen metadata a tajnou zprávu zničit až při
výslovném zobrazení přes POST, s heslovou frází poslanou druhým
kanálem jako pojistkou. Tento článek popisuje, které systémy načítají
odkazy bez ptaní a jak návrh přizpůsobit všem z nich.
Generátor jednorázových tajných odkazů v LinkPilotu funguje právě takto: načtení kvůli náhledu dostane jen kostru stránky. Tajná zpráva se načte a zobrazení se započítá teprve tehdy, když stránku spustí prohlížeč.
Výchozí způsob selhání
Většina chatovacích a e-mailových aplikací se pokusí vykreslit náhled, jakmile uvidí URL. Průběh vypadá takto:
- Uživatel vloží tajný odkaz do Slacku.
- Nástroj Slacku pro náhledy načte URL (pošle
GET; Slack toto chování popisuje v dokumentaci link unfurling). - Váš obslužný kód pro zobrazení bere požadavek jako zobrazení člověkem, zničí tajnou zprávu a vrátí její obsah.
- Slack dostane obsah zničené zprávy (nebo obecnou stránku) a vykreslí ho.
- Člověk klikne na odkaz, uvidí „už zobrazeno“ a napíše odesílateli o nový.
Nástroj pro náhledy nic zlého neměl v úmyslu. Váš obslužný kód zaměnil „někdo načetl URL“ za „příjemce si přečetl tajnou zprávu“. To jsou dvě různé události a celý problém návrhu je udržet je od sebe.
V kroku 3 se skrývá ještě horší varianta: pokud GET nástroje pro
náhledy dostal skutečný obsah, tajná zpráva teď leží v infrastruktuře
cizí firmy, která vykresluje náhledy. V nejlepším případě byla po
vytvoření náhledu zahozena. Nemáte ale jak to ověřit a žádná
auditní událost vám neřekne, že se to stalo.
Kdo načte odkaz dřív, než ho příjemce otevře?
Nástroje pro náhledy v chatech, bezpečnostní brány e-mailu, ochrana koncových zařízení, firemní proxy servery a rozšíření pro náhledy, a obvykle víc z nich najednou. „Slack vytváří náhledy“ problém zlehčuje. URL vloženou do moderního pracovního prostředí obvykle načte několik systémů dřív, než na ni klikne jakýkoli člověk:
| Kdo načítá | Kdy se spustí | Dá se rozpoznat? |
|---|---|---|
| Nástroje pro náhledy v chatech (Slack, Teams, iMessage, WhatsApp, LinkedIn) | V okamžiku odeslání zprávy | Obvykle ano, mají vlastní user agenty, například Slackbot-LinkExpanding |
| Bezpečnostní brány e-mailu (Mimecast, Proofpoint, Microsoft Defender) | Při doručení a často znovu při kliknutí | Často ne, mnohé se hlásí user agentem skutečného prohlížeče |
| Ochrana koncových zařízení / antivir | Když URL dorazí na počítač příjemce | Zřídka |
| Firemní webové proxy servery | Při kliknutí, před přeposláním požadavku uživatele | Zřídka |
| Rozšíření prohlížeče pro náhledy odkazů | Při najetí myší nebo načtení stránky | Ne, běží v relaci prohlížeče samotného uživatele |
Chování dodavatelů v této tabulce se mění. Konkrétní tvrzení
o branách berte jako „podle zveřejněných údajů z července 2026,
ověřte v aktuální dokumentaci“. Společný jmenovatel se ale nemění:
všechny tyto systémy posílají obyčejný GET, protože to je jediný
bezpečný a univerzální způsob, jak se podívat na URL, kterou nemáte
pod kontrolou.
Jak zabránit, aby náhled zničil jednorázový odkaz?
Na GET vracejte metadata a zprávu zničte až při výslovném POST.
Sémantika HTTP to už obsahuje:
RFC 9110, oddíl 9.2.1
definuje GET jako bezpečnou a idempotentní metodu, tedy požadavek,
který smí kdokoli volně poslat, protože nemá nic měnit. POST je
sloveso pro akci. Zobrazení proto řešte jako akci POST za viditelným
tlačítkem:
GET /s/abc123 → HTML page: "Click to reveal this secret"
POST /s/abc123 → burns the secret, returns the payload
GET od Slacku teď vrátí neutrální stránku s metadaty. Tajná zpráva
se zničí, až když člověk klikne na tlačítko. Skener, který respektuje
sémantiku HTTP, se obsahu vůbec nedotkne. Respektuje ji téměř každý,
protože posílat POST s vedlejšími účinky na libovolné URL by
rozbilo půlku webu.
Příklad krok za krokem
Sledujte jeden odkaz od začátku do konce. Vytvoříte tajnou zprávu s volbou Zničit po přečtení a s heslovou frází a URL vložíte do přímé zprávy ve Slacku a do e-mailu.
- Nástroj Slacku pro náhledy pošle
GET /s/abc123. Odpověď: malá stránka s metadaty, stav „active“ (aktivní), vyžadována heslová fráze. Žádné zobrazení se nezaznamená. Tajná zpráva žije. - Brána e-mailu příjemce přepíše URL v e-mailu a při doručení
ji načte kvůli analýze reputace. Stejný
GET, stejná metadata. Zpráva pořád žije. - Příjemce klikne na odkaz v e-mailu. Skener brány při kliknutí
URL načte ještě jednou (
GET) a pak prohlížeč přesměruje dál. - Prohlížeč načte stránku pro zobrazení, opět přes
GET. Stránka ukáže tlačítko pro zobrazení a pole pro heslovou frázi. Zobrazení se pořád nezaznamenalo. - Příjemce zadá heslovou frázi a klikne na zobrazení. Prohlížeč
pošle
POST /s/abc123. Zobrazení se zaznamená, obsah se vrátí a tajná zpráva se zničí. - Kdokoli, kdo URL načte potom, dostane místo obsahu výslovnou odpověď „už zobrazeno a zničeno“.
Pět načtení, jedno zobrazení. Ve firemním prostředí je takový poměr normální. Návrh, který ho nesnese, selže hned první den a odesílatel pak heslo prostě vloží do chatu.
Vícevrstvá obrana
Rozdělení na GET a POST
Pokryje každý slušně se chovající nástroj pro náhledy i skener, tedy drtivou většinu automatického provozu. Je to základ, všechno ostatní níže přidává další vrstvy.
Heslová fráze
Pokrývá to, co rozdělení nezvládne: sandboxy, které spouštějí JavaScript a se stránkou pracují, a k tomu nechtěná kliknutí lidí a přeposlané e-maily. Sandbox pro detonaci na tlačítko pro zobrazení klikne, ale nedokáže zadat heslovou frázi, která přišla jiným kanálem. Odkaz pošlete e-mailem a heslovou frázi přímou zprávou ve Slacku nebo SMS.
Filtrování robotů podle user agenta
Známé roboty pro náhledy (Slackbot, LinkedInBot, Twitterbot)
odfiltrujte dřív, než se dostanou k jakékoli logice zobrazení. Jako
pojistka navíc se to vyplatí, samo o sobě to ale nikdy nestačí:
bezpečnostní skenery se běžně hlásí user agentem skutečného prohlížeče
právě proto, aby se před nimi škodlivé stránky nemohly maskovat.
Krátká platnost
Omezte dobu, po kterou může vzniknout škoda. Po odkazu, který žil patnáct minut, zůstane ve skenerech, logech a historii chatu URL, která už nikam nevede.
Cache-Control: no-store
Nastavte ho u každé odpovědi se zobrazením, aby si žádný prostředník (firemní proxy, CDN, mezipaměť prohlížeče) neponechal kopii obsahu po jediném oprávněném přečtení.
Zvlášť o bezpečnostních branách e-mailu
Firemní brány si zaslouží vlastní oddíl, protože načítají dvakrát. Produkty této třídy (zdokumentovaným příkladem je Microsoft Defender Safe Links) přepisují každou URL v příchozí poště přes vlastní skenovací doménu. URL se obvykle načte jednou při doručení kvůli analýze reputace a znovu při kliknutí, než se člověk přesměruje na skutečný cíl.
Kdyby kterékoli z těchto načtení tajnou zprávu zničilo, příjemce by
vždy viděl mrtvý odkaz. Uživatelům takové selhání připadá náhodné,
ve skutečnosti je ale zcela deterministické. Rozdělení na GET/POST
obě načtení zvládne bez dalších nákladů, protože obě jsou obyčejné
GET. Přesměrování při kliknutí pak člověka dovede na stránku pro
zobrazení, kde proběhne POST.
Okrajové případy, které pořád škodí
- Sandboxy spouštějící JavaScript. Některá prostředí pro detonaci
stránku vykreslí a pracují s ní. Na
POSTza tlačítkem bez heslové fráze by agresivní sandbox v principu mohl kliknout. Pojistkou je heslová fráze. - Odkaz a heslová fráze stejným kanálem. Pokud obojí přijde v jednom e-mailu, veškerá obrana výše se zúží na „doufejme, že ten e-mail nikdo nečte“. Kanály vždy rozdělte.
- Přeposílání. Každé přeposlání do jiného chatu nebo poštovního systému spustí nové kolo náhledů. S rozdělením to neškodí, ale každý další krok znamená další logy, ve kterých URL zůstane, a to je argument pro krátkou platnost.
- Souběžná zobrazení. Když na zobrazení kliknou dva lidé najednou, zničení musí proběhnout v jednom nedělitelném kroku: uspěje přesně jeden požadavek a druhý dostane „už zobrazeno“. Implementace, která čtení a zničení provádí odděleně, může obsah vydat dvakrát.
Otestujte svůj nástroj
Než službě pro sdílení tajných zpráv svěříte skutečné přihlašovací údaje, proveďte tuto dvouminutovou kontrolu:
- Vytvořte testovací tajnou zprávu se zapnutou volbou Zničit po přečtení.
- Načtěte ji z terminálu, přesně tak to dělá nástroj pro náhledy:
curl -s -o /dev/null -w "%{http_code}" "<url>" - Otevřete odkaz v prohlížeči. Pokud uvidíte „už zobrazeno“, nástroj
zprávu zničí už při
GETa jeho odkazy není bezpečné vkládat do chatu ani e-mailu. - Pokud zpráva přežila, zobrazte ji v prohlížeči správným způsobem
a pak spusťte
curlznovu. Teď byste měli dostat výslovnou odpověď, že zpráva zmizela nebo byla zničena, ne její obsah.
Jak to řeší LinkPilot
Pro úplnost: právě tento návrh používají tajné odkazy v LinkPilotu.
GET na koncový bod pro zobrazení vrací jen metadata (stav a to, zda
je vyžadována heslová fráze). Zobrazení se zaznamená jen při výslovném
zobrazení přes POST. Heslové fráze se hashují algoritmem SHA-256 na
straně klienta a počet pokusů je omezen na pět za minutu z jedné IP
adresy u každé tajné zprávy. Každá odpověď se zobrazením nese
Cache-Control: no-store, zničené tajné zprávy a zprávy s vypršelou
platností vracejí HTTP 410 a uložený obsah je přepsán. Časová osa
auditu zaznamenává každou událost s IP adresou zahashovanou se solí,
která se mění každý den; nezpracovaná IP adresa se nikdy neukládá.
Všechny podrobnosti najdete na stránce bezpečnostní
architektura.
Vyzkoušejte zdarma, bez registrace
Samozničující zpráva
Pošlete poznámku, která po jednom přečtení zmizí.
Hranice tohoto návrhu
Poctivě řečeno: žádné z popsaných opatření tajnou zprávu nechrání po oprávněném zobrazení. Příjemce si obsah může zkopírovat, vyfotit obrazovku nebo ho přeposlat. Nepomůže to ani tehdy, když heslová fráze putuje spolu s odkazem. A nezabrání to člověku, kterému byl odkaz poslán omylem, aby ho otevřel dřív než zamýšlený příjemce. K tomu slouží auditní záznam: uvidíte nečekané zobrazení a přihlašovací údaje změníte.
Související články
- Jak fungují jednorázové tajné odkazy
- Proč URL prozrazují citlivé údaje
- Bezpečnostní architektura LinkPilotu
Zdroje
- IETF, RFC 9110: HTTP Semantics, section 9.2.1 Safe Methods.
- Slack API, Unfurling links in messages.
- Microsoft Learn, Safe Links in Microsoft Defender for Office 365.
