Auf Bluesky gehostete Website
(danielmangum.com)- Daniel Mangum zeigt, dass sich mithilfe des Blob-Uploads und der Record-Referenzstruktur des AT Protocol auf einen Bluesky-PDS hochgeladene
text/html-Dateien wie im Browser geöffnete Webseiten bereitstellen lassen - Der zentrale Mechanismus ist, dass ein hochgeladener Blob nicht sofort öffentlich ist; erst wenn ein Record den Blob referenziert, macht der PDS ihn öffentlich zugänglich
- Normale Bluesky-Image-Embeds erlauben nur MIME-Typen
image/*, aber Records unbekannter Lexicons oder Custom Embeds auf Basis von Open Unions können Referenzen auftext/html-Blobs speichern getBlobist ohne Authentifizierung erreichbar, und Anfragen anbsky.socialwerden zum tatsächlichen PDSporcini.us-east.host.bsky.networkweitergeleitet, der das HTML zurückliefert- Bluesky setzt für
getBlobCSP-Header undnosniffein und begrenzt normale Blob-Uploads auf 5 MB, aber für PDS-Betreiber bleiben die Belastungen durch Hosting beliebiger Dateien sowie Speicher- und Transferkosten bestehen
Wie man mit AT-Protocol-Blobs eine Website hochlädt
- Dieses Beispiel basiert weniger auf normalen Funktionen der Bluesky-App als auf der Funktionsweise des AT Protocol und der PDS-API
- Bluesky stellt einen PDS Entryway bereit, über den auf den PDS eines Nutzers zugegriffen wird, und exponiert mehrere PDS-Instanzen über die Domain
bsky.social - Einzelne PDS-Instanzen können auch direkt angesprochen werden; die Beispiel-Website öffnet sich am Endpoint
com.atproto.sync.getBlobvonporcini.us-east.host.bsky.network - Vor der Veröffentlichung des Beitrags gab es Austausch mit dem Bluesky-Team; dieses Verhalten ist keine beabsichtigte Nutzung der Anwendung, aber ein bekanntes Verhalten und kein Verfahren zur Offenlegung einer Sicherheitslücke
Warum Records und Blobs getrennt sind
- Im AT Protocol werden Anwendungsdaten grob in Records und Blobs unterteilt
- Records sind die zentralen, von Nutzern erstellten Entitäten und können Struktur sowie Metadaten enthalten
- Blobs sind größere unstrukturierte Daten wie Bilder und werden normalerweise erst sichtbar, wenn ein Record sie referenziert
- Wenn man in Bluesky einen Post mit Bild erstellt, wirkt das für Nutzer wie ein einzelner Vorgang, auf API-Ebene sind Blob-Upload und Record-Erstellung jedoch getrennt
- Laut Blob Specification muss ein Blob zuerst auf den PDS hochgeladen werden, bevor ein Record ihn referenziert
- Da der Server beim Upload nicht wissen kann, in welchem Lexicon der Blob verwendet wird, gelten beim initialen Upload nur allgemeine Blob-Beschränkungen; Lexicon-basierte Beschränkungen werden erst beim Erstellen des Records angewendet
- Erfolgreich hochgeladene Blobs landen in einem temporären Speicher; in diesem Zustand können sie nicht heruntergeladen oder verteilt werden und erscheinen auch nicht in der Ausgabe von
listBlobs - Wenn die Record-Erstellung erfolgreich ist und dieser Record den Blob referenziert, schaltet der Server den Blob in einen öffentlich zugänglichen Zustand um
HTML-Blob hochladen und öffentlich machen
- Ein Authentifizierungstoken erhält man, indem man über die XRPC-Methode
com.atproto.server.createSessionNutzer-Anmeldedaten austauscht - Im Beispiel wurde mit
com.atproto.sync.listBlobsdie vorhandene Zahl der Blobs geprüft; vor dem Upload lag sie bei391 - Der Website-Inhalt ist eine einfache
index.html-Datei und wird mitcom.atproto.repo.uploadBlobhochgeladenContent-Typeisttext/html- Die zurückgegebenen Blob-Metadaten enthalten die CID
bafkreic5fmelmhqoqxfjz2siw5ey43ixwlzg5gvv2pkkz7o25ikepv4zeq,mimeType: text/htmlundsize: 268
- Direkt nach dem Upload war der Abruf über
com.atproto.sync.getBlobnicht möglich, und die Zahl inlistBlobsblieb ebenfalls bei391 - Wenn man den HTML-Blob als Image Embed in einem Bluesky-Post referenziert, schlägt dies fehl, weil das Schema
app.bsky.embed.imageden MIME-Typimage/*verlangt- Belässt man
text/html, tritt der FehlerWrong type of file. It is text/html but it must match image/*.auf - Ändert man
mimeTypeinimage/jpeg, tritt ein Fehler auf, weil der gespeicherte Blob-MIME-Typ und der referenzierte MIME-Typ unterschiedlich sind
- Belässt man
Blob über einen unbekannten Lexicon-Record veröffentlichen
- Der Blob-Typ ist nicht Bluesky-spezifisch, sondern Teil des AT-Protocol-Datenmodells
- Die Bluesky-PDS-Implementierung ist Open Source, und
findBlobRefsdurchsuchtLexValuerekursiv nach Referenzen mit$type: blob - Da PDS mit der Zeit neue Lexicons unterstützen müssen, müssen sie auch Lexicons verarbeiten können, die sie selbst nicht kennen
- Als ein Record vom Typ
com.danielmangum.hack.websiteerstellt und der HTML-Blob referenziert wurde, speicherte der PDS den Record- Die Antwort enthielt
validationStatus: unknown - Weil der PDS das Lexicon
com.danielmangum.hack.*nicht kannte, konnte er es nicht validieren, erlaubte aber das Speichern des Records
- Die Antwort enthielt
- Danach stieg die Zahl in
listBlobsauf392, was bestätigte, dass der Blob dauerhaft gespeichert wurde getBlobkann ohne Authentifizierungstoken aufgerufen werden, weil auch nicht authentifizierte Akteure, die Records zusammen mit Blobs verarbeiten müssen, den Blob abrufen können müssen- Der
getBlob-Aufruf aufbsky.sociallieferte per 302-Redirect die tatsächliche PDS-URL zurück; folgt man dem Redirect mit-L, wird der HTML-Inhalt unverändert zurückgegeben
Sicherheits-Header, CDN und die Last direkter Zugriffe
- Die Security Considerations der AT-Protocol-Blob-Spezifikation behandeln Content-Sicherheitsrisiken, die entstehen, wenn beliebige von Nutzern hochgeladene Dateien von einem Webserver ausgeliefert werden
- Ein typisches Beispiel sind XSS-Probleme, bei denen Skripte oder SVG-Inhalte im selben Origin ausgeführt werden
- Für den Endpoint
getBlobist der Einsatz einer Content Security Policy praktisch unverzichtbar - Die direkte Bereitstellung von Blob-Speichern für Browser und Web-Agents wird faktisch nicht unterstützt; Anwendungen sollten stattdessen über ein unabhängiges CDN, einen Proxy, Webservices usw. gehen
- Der
getBlob-Handler des Bluesky-PDS setzt die empfohlenen Sicherheits-Headerx-content-type-options: nosniffcontent-security-policy: default-src 'none'; sandbox
- Die Standardgrenze für Blob-Uploads liegt bei 5 MB
- Normale Image-Blobs der Bluesky-Anwendung werden nicht direkt vom PDS bereitgestellt, sondern als CDN-URLs von
cdn.bsky.app- Es gibt getrennte URLs für Feed-Thumbnails und Full-Size-Versionen
- Der Post-Record enthält die Bild-CID, und die Anwendung muss wissen, wie die Bereitstellung über das CDN funktioniert
- Direkter Zugriff über
getBlobbleibt laut GitHub-Issue wegen Image-Labeling, Export von Nutzerinhalten und künftiger Use Cases bestehen- In derselben Diskussion wird auch die Möglichkeit erwähnt, dass Nutzer Inhalte hotlinken oder Bluesky wie kostenloses Hosting verwenden
- Der ursprünglichen Implementierung fehlten Sicherheits-Header; diese wurden später hinzugefügt
- Klassische soziale Plattformen können Blobs beim Upload stärker einschränken, weil die zulässigen Content-Typen begrenzt sind; die Erweiterbarkeit von Bluesky und AT Protocol erfordert jedoch eine komplexere Verarbeitung
Custom Embed per Open Union in einen Post einfügen
- Der Typ
app.bsky.feed.postdefiniert die Liste gültiger Embeds als Union - Im AT-Protocol-Lexicon sind Unions standardmäßig open, sofern sie nicht ausdrücklich
closedsind- Da bei künftigen Schema-Revisionen Typen hinzukommen können, sollten Implementierungen bei der Validierung tolerant sein
- Ist das Flag
closedgesetzt, ist die Typmenge fixiert
- Die Embed-Union eines Bluesky-Posts ist nicht als
closedmarkiert - Daher lassen sich Posts auch mit einem nicht aufgezählten Embed-
$typeerstellen - Im Beispiel wurde in einen
app.bsky.feed.post-Record ein Embedcom.danielmangum.hack.siteseingefügt, der wiederum den HTML-Blob referenziertvalidationStatusder Antwort istvalid- In der Bluesky-Anwendung wird dieses Embed stillschweigend ignoriert
- Der Inhalt und die Referenz bleiben im Record dauerhaft gespeichert, sodass andere Anwendungen dieses Embed rendern können
- Solche Lexicon-Eigenschaften können genutzt werden, um kleine Erweiterungen auf bestehende Use Cases aufzusetzen; als Beispiel wird die Möglichkeit genannt, kleine Code-Snippets innerhalb eines Posts in einer WebAssembly-Sandbox auszuführen
1 Kommentare
Meinungen auf Hacker News
Ich fand es gut, dass Daniel direkt beim Team nachgefragt hat, und Blob-Hosting ist ein Bereich, der zwangsläufig weiter angepasst werden muss, während man die Missbrauchswege besser versteht.
Im Moment ist es spannend zu sehen, dass solche Nutzungen tatsächlich funktionieren, und PDS ist von der Struktur her so gedacht, dass es zu einem Datenbank-Host wird, so wie ein Webserver Websites hostet.
Früher war er toll zum Herumspielen, und ich wusste nicht, dass er zu Bluesky gewechselt ist; das ist ziemlich interessant.
Bsky unterstützt bereits die Methode, Nutzer-Domains per ALIAS an redirect.bsky.com anzubinden: https://bsky.app/profile/jacob.gold/post/3kh6rnpdzmp2v
Ich war neugierig, in welchem Sicherheitskontext das läuft, und habe mir die PDS-Blob-URL mit
curlangesehen; in den Response-Headern standen unter anderemaccess-control-allow-origin: *,content-security-policy: default-src 'none'; sandboxundx-content-type-options: nosniff.access-control-allow-origin: *ist interessant, weil es bedeutet, dass JavaScript auf Webseiten beliebiger Domains mitfetch()auf diese Inhalte zugreifen kann, unddefault-src 'none'; sandboxist gut, weil es eine sehr restriktive Einstellung ist, die das Laden zusätzlicher Skripte oder Bilder verhindert und auch die Ausführung von JavaScript blockiert: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Co...ratelimit-limit: 3000scheint vermutlich ein IP-basiertes Limit zu sein.Der Vorschlag am Ende des Artikels, WebAssembly zu verwenden, geht in die richtige Richtung, und das Problem mit Link-Klicks ließe sich begrenzen, indem man nicht vertrauenswürdigen Code in ein iframe legt und im Parent per
child-srcnur bestimmte Domains oderdata:erlaubt.https://github.com/w3c/webappsec/issues/656#issuecomment-246...
https://www.w3.org/TR/CSP3/#exfiltration
sandboxtrotzdemdefault-srcbraucht oder ob das eine redundante Einstellung ist.Ich bin ziemlich gespannt auf die Möglichkeit, Bluesky als Blob-Datenspeicher zu verwenden.
Zusammen mit einem Freund habe ich überlegt, DOOM-WADs in Bluesky zu speichern und „Map Packs“ wie Posts zu teilen; wenn man Accounts, Listen oder Starter Packs folgt, könnte man Clients wie GZDoom so anpassen, dass sie die von diesen Accounts hochgeladenen WADs suchen und anzeigen können.
Das wäre ähnlich wie der Steam Workshop, nur eben über Bluesky.
Ich weiß auch nicht, ob Bluesky jemals Richtlinien für die Nutzung als Blob-Speicher erwähnt hat; DOOM-Dateien sind klein und daher ein gutes Beispiel, aber ich frage mich, ob das missbraucht werden könnte, um großen Server-Speicherbedarf auszulagern.
Ich habe diese konkrete Ära zwar nicht miterlebt, aber wie BlueSky-Nutzer in technisch tiefes Wasser springen, erinnert mich an die Zeit, als Leute auf MySpace zum ersten Mal HTML gelernt haben.
Der Social-Media-Markt ist heute viel stärker gesättigt, aber ich frage mich, ob aus BlueSky eine neue Generation von Programmierern hervorgehen kann.
Bluesky bietet nur die erste Stufe; alles danach wirkt wie ein ziemlich großer Sprung.
Mit HTTP/HTML kann man selbst jemandem, der nur grundlegendes Python oder eine andere Programmiersprache kennt, in 14 Minuten zeigen, wie man einen Server von Grund auf baut.
Ich denke zwar, dass man ein hashadressiertes Kommunikationsprotokoll braucht, um zu verhindern, dass Tech-Giganten Communities ausbeuten, aber ich bin nicht sicher, ob das AT Protocol seine Ziele gut genug trifft, um eine Revolution wie HTTP auszulösen.
Einer der Kernpunkte ist, dass der hier behandelte PDS nicht das Bluesky-Produkt selbst ist, sondern Teil des Personal Data Server, wodurch er am Ende wie ein unbegrenzter kostenloser Datenspeicher wirken kann.
Der Abo-Dienst, den das Bluesky-Team gelegentlich erwähnt hat, könnte mit solchen Dingen zusammenhängen, und Hosting, das auf dem PDS mehr Speicherplatz, Bandbreite oder hochauflösende Videos bietet, scheint sich gut als Premium-Tier verkaufen zu lassen.
Man dürfte ihn auch anderswo hosten können, daher scheint die Aussage zu stimmen, dass man über die Bluesky-App hinaus damit interagieren kann.
Das Phänomen, dass, sobald man es möglich macht, irgendetwas ins Internet zu stellen, am Ende irgendjemand darauf beliebiges File-Hosting versucht, braucht offenbar einen Namen.
In der Zeit der unbegrenzten Nutzung gab es mehrere Open-Source-Projekte, die versuchten, Dateisysteme in Gmail und Ähnlichem zu sichern; nach dem Start von Drive wurde es noch schlimmer.
Kostenlose Dienste müssen solche Probleme vorhersehen und standardmäßig Limits setzen.
https://en.wikipedia.org/wiki/Inner-platform_effect
Wenn solche Themen interessant sind, lohnt sich auch ein Blick auf atfile: https://github.com/electricduck/atfile
Ziemlich cool, und man kann sich direkt das interessante GitHub-Issue ansehen, das unten im Beitrag verlinkt ist.
Auch die bekannte Bluesky-Person pfrazee taucht dort auf: https://github.com/bluesky-social/atproto/issues/523
Ich setze große Hoffnungen in AT, und im Fediverse gibt es sicher viele kluge Leute, die großartige Arbeit geleistet haben, aber dieses Paradigma wirkt nachhaltiger und realistischer.
Der Grundansatz ist, es zentralisiert bereitzustellen, aber bei Bedarf oder für Power-User echte Unterstützung für Dezentralisierung zu bieten.
Es braucht einen Weg, aus dem Firehose-Mirroring eine Rendite zu erzielen; denkbar wären etwa eine Discord-Alternative, bei der einige Nutzer für das Hosting längerer Videos zahlen, eine Patreon-artige Struktur, bei der Relays Zugriffs- und Entschlüsselungsschlüssel verwalten und dafür Gebühren nehmen, oder ein sozialer Marktplatz wie Bandcamp.
Jedenfalls ist es eine offene Plattform, also gibt es schon jetzt keinen Grund, warum man das nicht tun könnte.
https://www.blockchaincapital.com/blog/bluesky-13m-users-and...
https://bsky.social/about/blog/09-11-2024-video
Ich habe das Gefühl, dass diese Methode für Phishing oder die Verbreitung von Malware missbraucht werden könnte.
Wenn man eine Hosting-Seite baut, scheint es fast ein Gesetz der Informatik zu sein, dass irgendjemand sie für bösartige Zwecke nutzen will.
Bei Matrix-Anhängen gab es dasselbe Problem.
*.bsky.networkvon Google Safe Browsing, Palo Alto, Bluecoat und anderen blockiert werden.Das ist ein direkter Link zum Bluesky-Server des Autors, also zum PDS, und damit natürlich unter Kontrolle des Autors.
Die jüngsten API-Änderungen bei Strava haben mich daran erinnert, wie eingeschränkt der Zugriff auf die auf ihrer Plattform gespeicherten Daten ist.
Als dominierender Dienst im Fitnessbereich könnten sie Funktionen nach und nach hinter eine Abo-Schranke verschieben.
Auch wenn es Datenschutz- oder Sicherheitsbedenken gibt, frage ich mich, ob das AT Protocol als Speicherplattform für GPX- oder FIT-Dateien geeignet sein könnte.
Allerdings unterstützt das AT Protocol meines Wissens noch keine privaten oder eingeschränkt öffentlichen Beiträge, und für Strava-Zwecke halte ich diese Funktion für ziemlich zentral.