Warum das Einfügen eines Einmal-Links in einen Chat mit Linkvorschau den Lesevorgang nicht immer schon verbraucht
Eine Karte unter der Nachricht heißt nicht, dass die Gegenstelle den Geheimtext schon gelesen hat. Slack, Discord oder Microsoft Teams schicken für die Linkvorschau ein HTTP-GET an die Leseseite. Dieser Abruf liest in der Regel Titel und Kurztext. Er klickt nicht auf Öffnen und ansehen und sendet den Schlüssel hinter # nicht mit. Der Artikel trennt „die Karte ist da“ von „ein Lesen ist verbraucht“ und beschreibt einen Test, den Sie mit einem Dummy-Link sofort nachziehen können. Das ist keine Bedienungsanleitung für das Formular auf der Erzeugen-Seite.
Zuerst klären, welche Schicht die Karte holt
Dieser Artikel beantwortet nur, warum ein Einmal-Link in einem Chat mit Linkvorschau den Lesevorgang nicht immer schon verbraucht hat. Er ersetzt weder das Formular auf Einmal-Link noch den älteren Text, warum # nicht in Server-Logs kommt.
Welche Schicht eine Vorschaukarte wirklich holt
Die Karte erscheint wenige Sekunden um das Senden herum. Die Anfrage kommt von den Servern des Chat-Produkts, nicht vom Finger der Gegenstelle.
Wenn Sie eine Adresse der Form https://…/s.html?id=…#… in Slack, Discord oder Microsoft Teams einfügen, erscheint oft zuerst eine kleine Karte unter dem Eingabefeld oder der Nachricht: ein Titel, ein Satz Beschreibung, manchmal ein Icon. Viele lesen das als „der Link ist schon geöffnet worden“. Die Reihenfolge ist umgekehrt. Das Chat-Produkt schickt zuerst ein HTTP-GET an diese Adresse, zieht aus dem HTML og:title, og:description oder ein schlichtes <title> und zeichnet erst dann die Karte. Die Gegenstelle muss bis dahin noch nichts angeklickt haben.
Slack hat das auf Deutsch und auf Englisch festgehalten. Die Hilfeseite Links teilen und persönliche Vorschau-Einstellungen festlegen nennt das Verhalten Linkvorschau: Eine vollständige URL wird unter der Nachricht zu einer Textvorschau erweitert. Technisch beschreibt Slack dasselbe unter Unfurling links in messages als klassisches Link-Unfurling. Der Roboter, der die Seite holt, nennt sich Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots). Auf Slack Robots steht: Er holt so wenig wie möglich von der Seite (über HTTP Range) und sucht oEmbed-, Twitter-Card- und Open-Graph-Tags. Ein Bild, Video oder eine Audiodatei holt er nur, wenn ein Tag darauf zeigt, um die Datei zu prüfen. Antworten werden dienstweit etwa 30 Minuten zwischengespeichert. Die Seite sagt nicht, dass JavaScript ausgeführt oder ein Button für die absendende Person geklickt wird.
Sendet ein Browser – oder ein Vorschau-Roboter, der sich wie einer verhält – dieses GET, gehört der Teil nach # nicht zur Request-Zeile. Die IETF definiert das Fragment in RFC 3986 §3.5 als clientseitige Kennung. Der Server verwendet sie nicht, wenn er den URI verarbeitet. Selbst wenn der Roboter die ganze Zeichenkette aus dem Eingabefeld kopiert, endet die Anfrage bei UsePwd deshalb meist bei s.html?id={id}. Warum der Schlüssel nicht in Zugriffsprotokollen steht, steht im älteren Artikel Warum das #-Fragment einer URL nicht in Server-Logs steht. Hier geht es um die nächste Schicht: Zählt ein GET, das den Schlüssel nie getragen hat, als „ein Lesen“.
Die brauchbare Frage lautet nicht „hat das Chat-Produkt diese URL gesehen“. Sie lautet „hat dieses GET die Geheimtext-API erreicht“. Eine Karte beweist nur, dass der Titel gelesen wurde. Ob der Geheimtext noch da ist, prüfen Sie getrennt.
Warum das erste GET kein Lesen ist
Behandelt ein Tool „Geheimtext holen“ und „Leseseite öffnen“ als dieselbe Anfrage, verbraucht der Vorschau-Bot das einzige Lesen. Sind die Schritte getrennt, sind sie nicht mehr dieselbe Aktion.
Viele Einmallinks hängen das Geheimnis an genau die URL, die der Vorschau-Bot per GET holt. Der Roboter fragt einmal; der Server liefert den Text und löscht den Datensatz. Die Gegenstelle öffnet danach „bereits gelesen“ oder eine 404. Dieser Fehlschlag ist häufig. Slack verbrennt das Geheimnis nicht „böswillig“. Die Implementierung behandelt ein cachebares GET – die Methode, die RFC 9110 weiter als sicher beschreibt – als die Aktion, die den Geheimtext zerstört.
Der UsePwd-Einmal-Link zerlegt die Arbeit in drei Schritte. Beim Erzeugen verschlüsselt der aktuelle Tab mit Web Crypto und AES-256-GCM. Klartext höchstens 32 KB. Hochgeladen werden nur Geheimtext, eine Gültigkeit und ein Lesecount. Ablauf kann 1 Stunde, 24 Stunden, 7 Tage oder „nur nach dem Lesen verbrennen“ ohne Uhr-TTL sein. Lesevorgänge sind 1–10, Standard 1. Die weitergegebene URL sieht aus wie s.html?id={id}#{key}. Erzeugen und Lesen sind sofort nutzbar – weder Sender noch Empfänger registrieren sich. Der Server speichert nur Geheimtext. Er sieht keinen Klartext, und es gibt kein Konto, über das sich das Geheimnis einem Nutzer zuordnen ließe.
Öffnet die Gegenstelle die Leseseite, fragt der Tab zuerst unter /api/secrets/{id}/status, ob der Geheimtext noch da ist. Die Antwort ist active, burned oder expired. Der Zähler steigt nicht, der Datensatz bleibt. Erst nach Öffnen und ansehen holt der Browser /api/secrets/{id}, lädt den Geheimtext und entschlüsselt lokal mit dem Schlüssel hinter #. Ist der beim Erzeugen gesetzte Count erreicht, löscht der Server den Geheimtext; ein späterer Abruf liefert 410. Ein Vorschau-Bot, der beim HTML der Leseseite stehen bleibt, hat in der Regel keinen Schlüssel und klickt den Button nicht.
Liefert die statische Leseseite. Der Titel lautet „Einmal-Link öffnen“. Darin steht kein Klartext. Vorschaukarten bleiben meist hier.
Antwortet nur: noch da, verbrannt oder abgelaufen. Wiederholtes Fragen zählt nicht als Lesen.
Dieser Aufruf zählt. Nach dem Standard von 1 wird der Geheimtext gelöscht. Auf der Leseseite ist das Öffnen und ansehen.
Die Leseseite schreibt einen Satz, den Sie sofort prüfen können: Der Button „kann einen Aufruf verbrauchen“. Ohne Skripte gibt es keinen Entschlüsselungsweg; ein <noscript>-Block sagt das. Ein Vorschau-Bot, der nur HTML liest und kein JavaScript ausführt, schickt noch nicht einmal die Statusabfrage. Führt ein In-App-Browser Skripte aus, bleibt er bei „Geheimtext ist noch da“, bis jemand den Button klickt.
Welche Bots kommen und was sie mitnehmen
Viele Produkte können eine Karte zeichnen. Was sie mitnehmen, ist der Seitenkopf – nicht der Schlüssel hinter # und nicht entschlüsselter Klartext.
Slacks Link-Expanding-Roboter, Discords Embed-Crawler und die serverseitige Anfrage, mit der Microsoft Teams eine Karte baut, gehören zur selben Klasse: GET auf die Seite, dann Titel und Beschreibung im HTML suchen. Discord kennzeichnet den Crawler als Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com). Öffentliche Beschreibungen von Discordbot stimmen in einer Grenze überein, die Sie als Arbeitsannahme nutzen können: Er parst das vom Server gelieferte HTML und führt kein JavaScript aus. Slack ist bei einer anderen Grenze ausdrücklich. Nach Versuchen mit robots.txt hält Slack die Datei nicht mehr wie ein Suchcrawler ein, weil Unfurling „im Auftrag eines Menschen“ geschieht und die Website nicht durchkämmt wird. noindex auf der Leseseite kann Suchmaschinen vom Indexieren abhalten. Die Karte im Kanal hält das nicht auf.
Die UsePwd-Leseseite ist eine temporäre Geheimtext-Ansicht. Sie trägt noindex, nofollow und steht nicht in der Sitemap. Der Dokumenttitel ist fest „Einmal-Link öffnen“. Die Beschreibung sagt nur, dass die Entschlüsselung in diesem Tab endet und der Schlüssel hinter # sitzt. Erscheint eine Vorschaukarte, sieht der Kanal diese allgemeine Zeile – nicht das Passwort, das Token oder den Tickettext, den Sie eingegeben haben. Das kann gleichzeitig wahr sein mit „im Zugriffsprotokoll steht kein Fragment“. Die Karte beweist, dass jemand die Leseseite per GET geholt hat. Im Log fehlt weiter der Schlüssel hinter #.
Slack schreibt, dass Unfurl-Ergebnisse derselben URL etwa 30 Minuten zwischengespeichert werden. Denselben Testlink zweimal kurz hintereinander in einen Kanal zu kleben, erzeugt deshalb nicht unbedingt einen zweiten Abruf. Ob ein Bot da war, sehen Sie an einem User-Agent wie Slackbot-LinkExpanding oder Discordbot in Ihrem eigenen Zugriffsprotokoll – nicht daran, wie oft die Karte neu zeichnet. Ein GET auf s.html heißt weiter nicht, dass /api/secrets/{id} aufgerufen wurde.
Wann ein Lesen wirklich verbraucht wird
„Nicht immer verbraucht“ heißt nicht „nie verbraucht“. Ein Besuch, der Öffnen und ansehen klicken kann, ist der Besuch, der die Geheimtext-Schicht erreicht.
Der übliche Verbraucher ist die Gegenstelle: Sie öffnet den vollständigen Link, sieht „Geheimtext ist noch da“ und klickt Öffnen und ansehen. Der Standardcount ist 1. Nach diesem erfolgreichen Abruf löscht der Server den Geheimtext. Derselbe Link zeigt danach „Bereits verbrannt“. Setzen Sie beim Erzeugen 2 oder mehr Lesen, bleibt der Geheimtext nach den ersten Abrufen, bis der Zähler die Obergrenze erreicht. Ablauf löscht ebenfalls: Standard 24 Stunden, sonst 1 Stunde oder 7 Tage. „Nur nach dem Lesen verbrennen“ löscht nach Count, nicht nach der Uhr.
Die zweite Klasse ist eine Umgebung, die Skripte ausführt und einen Klick simuliert. Manche Mail-Security-Gateways und Link-Sandboxes öffnen die URL in einem isolierten Browser. Manche klicken zusätzlich den primären Button. Das ist keine „Karte zeichnen“ mehr. Das ist ein zweiter, menschenähnlicher Besuch. Klickt die Sandbox Öffnen und ansehen, ist das Lesen verbraucht und die Gegenstelle sieht später den verbrannten Zustand. Das prüfen Sie am Bericht des Gateways. Aus der Chat-Karte können Sie es nicht ableiten.
Die dritte Klasse ist, die Geheimtext-API selbst zu posten. Die Adresse der Leseseite ist s.html?id=. Der Aufruf, der ein Lesen verbraucht, ist /api/secrets/{id}. Gewöhnliche Nutzer kopieren die zweite nicht. Wenn jemand diese API-URL in einen Kanal mit Linkvorschau einfügt und das Produkt das erste GET als Abruf behandelt, kann das Lesen schon in der Vorschau weg sein. Die weitergegebene Form von UsePwd ist nicht diese Adresse. Die Erzeugen-Seite kopiert den Leseseiten-Link mit #.
Eine Vorschau, die kein Lesen verbraucht hat, heißt nicht, dass das Geheimnis nur für die Gegenstelle existiert. Das Chat-Produkt speichert weiter die volle URL. Eine Workspace-Administration kann den Verlauf exportieren. Das Leselimit steuert, wie lange Geheimtext auf dem Server lebt. Es steuert nicht, wer diese Adresse aus dem Kanal noch öffnen kann.
Wie Sie eine Vorschau sofort prüfen
Ziel ist nicht der Beweis „kein Chat-Produkt der Welt liest je Geheimtext“. Ziel ist der Beweis: Nachdem die Karte da ist, wurde die Geheimtext-API noch nicht aufgerufen.
-
01
Einen Dummy-Text vorbereiten, den Sie nicht wirklich übergeben
Tippen Sie keinen gerade verwendeten API-Schlüssel und kein Login-Passwort. Öffnen Sie Einmal-Link, geben Sie
PreviewCard-20260905ein, lassen Sie die Lesevorgänge auf dem Standard 1 und den Ablauf auf 24 Stunden. Die Seite ist sofort nutzbar – ohne Registrierung. Die Schritte vergleichen eine Karte mit den APIs. Sie sind kein Weg, diese Zeichenkette jemand anderem als echtes Geheimnis zu geben. -
02
Den vollständigen Link sichern, dann die Leseseite selbst öffnen
Nach dem Erzeugen sollten Sie
s.html?id=und ein#-Segment sehen. Öffnen Sie denselben Link im aktuellen Browser. Die Seite sollte bei „Geheimtext ist noch da“ stehen und Öffnen und ansehen zeigen. Klicken Sie den Button noch nicht. Drücken Sie F12 und öffnen Sie das Netzwerk-Panel. Sie sollten eine Anfrage an/api/secrets/{id}/statussehen. Einen Geheimtext-Abruf an/api/secrets/{id}ohne das Suffix/statussollten Sie noch nicht sehen. -
03
Denselben Link in einen Testkanal mit Linkvorschau einfügen
Nutzen Sie einen Slack-Kanal, den nur Sie sehen, eine Discord-Direktnachricht an sich selbst oder einen anderen Testraum. Warten Sie auf die Karte. Der Titel sollte nahe bei „Einmal-Link öffnen“ liegen.
PreviewCard-20260905sollte nicht erscheinen. Aktualisieren Sie die Leseseite, oder öffnen Sie denselben Link in einem Fenster, das den Button nicht geklickt hat. Dort sollte weiter „Geheimtext ist noch da“ stehen. Steht dort schon „Bereits verbrannt“, hat ein anderer Besuch die Geheimtext-API erreicht. Das ist nicht „die Karte selbst ist ein Lesen“. -
04
Wenn Sie Zugriffsprotokolle haben, den User-Agent zuordnen
Im Vorschaufenster sehen Sie typischerweise ein GET auf
/de/s.html?id=…. Der User-Agent kannSlackbot-LinkExpandingoderDiscordbotenthalten. Im selben Fenster sollte kein erfolgreicher Abruf von/api/secrets/{id}stehen. Slack speichert dieselbe URL etwa 30 Minuten zwischen; ein zweites Einfügen in diesem Fenster erzeugt nicht unbedingt einen zweiten Abruf. -
05
Erst dann Öffnen und ansehen klicken und das verbrauchte Lesen bestätigen
Klicken Sie jetzt auf den Button. Das Netzwerk-Panel sollte die Geheimtext-Anfrage zeigen, die Seite den Dummy-Text. Schließen Sie sie und öffnen Sie denselben Link erneut. Dort sollte „Bereits verbrannt“ stehen. Dieser Schritt existiert, damit „nach dem Button“ und „nach der Karte“ zwei Zustände sind, die Sie gesehen haben. Verwerfen Sie den Link danach. Weisen Sie ihn keiner echten Gegenstelle neu zu.
Müssen Sie einer anderen Person nur einen neuen Schlüssel übergeben, kleben Sie den Klartext nicht „für eine Testkarte“ in den Kanal. Halten Sie Dummy-Text und echtes Geheimnis getrennt. Die echte Übergabe läuft weiter über den Einmal-Link. Zum zweiten Risiko nach einem Leak der Umgebungsvariablen siehe Nach einem Leak der Cloud-Umgebungsvariablen gehört der neue Schlüssel nicht in den Chat. Jener Artikel heißt „den API-Schlüssel selbst nicht in durchsuchbaren Verlauf kleben“. Dieser heißt „nach dem Einfügen des Links: auf welcher Schicht bleibt der Vorschau-Abruf stehen“.
Was der Chat behält, wenn der Zähler nicht fällt
„Die Karte hat den Geheimtext nicht verbrannt“ als „dieser Link hat den Kanal verlassen“ zu lesen, lässt Grenzen aus, die Sie ebenfalls prüfen können.
Das Chat-Produkt speichert die ganze Adresse, die Sie eingefügt haben. Wer den Verlauf durchsuchen, einen Workspace exportieren oder ein Backup öffnen kann, kann die Leseseite erneut öffnen. Solange Lesen übrig sind, kann eine spätere Person weiter Öffnen und ansehen klicken und Klartext sehen. Ist der Count verbraucht, bleibt im Verlauf ein verbrannter Link plus der Titel, den die Karte zeigte. Ein Admin-Export kann Geheimtext, den der Server schon gelöscht hat, nicht wiederherstellen. Er kann auch „in diesem Kanal stand einmal die volle URL“ nicht ungeschehen machen.
Screenshots und Weiterleiten sind eine weitere Kopie. Fängt jemand Klartext nach einem erfolgreichen Lesen ein oder leitet den Link in einen anderen Kanal mit Linkvorschau weiter, wandert die Grenze von „dieses GET“ zu „wer sitzt auf dem nächsten Hop“. Der Einmal-Link begrenzt, wie lange Geheimtext auf dem Server lebt und wie oft er geholt werden kann. Er hält die Gegenstelle nicht vom Screenshot ab. UsePwd hat kein Konto und keinen Tresor und kann einen verlorenen Link nicht nach Nutzer wiederfinden. Dauerablage oder Sync über mehrere Geräte gehört in einen eigenen Passwortmanager. Zur Identität siehe Über uns.
Dateien sind ein dritter Weg. Ein lokales Backup einer einzelnen Datei bis 5 GB läuft über Datei verschlüsseln, Ausgabe .lock / .enc. Die Datei wird standardmäßig nicht hochgeladen. Die Passphrase selbst erzeugen Sie im Bereich 6–128 im Passwort-Generator und prüfen die Stärke unter Passwort prüfen. Diese Seiten sind wie dieser Artikel sofort nutzbar. Lesen Sie „die Vorschau hat kein Lesen verbraucht“ nicht als „in jeden Kanal kleben und es ist sicher“. Chatverlauf und Vorschau-Abruf sind nicht dieselbe Schicht.
Was nach einer Linkvorschau gefragt wird
Diese vier Antworten bleiben an der Grenze dieses Artikels. Sie wiederholen nicht die Buttons der Erzeugen-Seite.
Danach eine Vorschaukarte prüfen
Der Artikel beantwortet, warum eine Linkvorschau den Lesevorgang nicht immer schon verbraucht. Um einen Dummy-Link zu erzeugen, den Sie nicht wirklich übergeben, und ihn in einen Testkanal zu kleben, öffnen Sie Einmal-Link. Sie registrieren sich nicht zuerst.