With the full upstream history the common ancestor could be searched rather than guessed: measuring tree distance, not dates, over every develop commit in the import window. deadd548 from 2026-05-08 wins with 43 differing files against 783 for the tag we wrongly assumed. Thirty-one of those are mode-only, the historical import bug, and the content remainder is precisely our own Discord feature plus LICENSE and CHANGELOG. Tested in a throwaway clone rather than asserted: without the graft there is no merge-base, with it deadd548 becomes one, and merging three months of develop yields 32 conflicting files. Only four are source, and they are exactly our patches - the rest are GitHub workflows we do not use and the lockfile. One intermediate result was worthless and nearly passed as success: merging v1.12.26 reported zero conflicts while not running at all, because the tag was fetched shallow and carries a single commit. Checking MERGE_HEAD is what caught it. The real gain is not the number. The issue warns that if Element moves a viewmodels file during the MVVM rework, our lines vanish without a conflict and git says nothing. With a genuine ancestor, git says something. Adopting this is ADR-worthy either way - a shared replace ref or a one-time unrelated- histories merge - so the decision stays with sorb.
12 KiB
type, id, status, created, milestone, priority, projekt, gitlab_iid, related
| type | id | status | created | milestone | priority | projekt | gitlab_iid | related |
|---|---|---|---|---|---|---|---|---|
| issue | 0099 | open | 2026-08-06 | M1 | medium | threadnet-web | 12 |
Upstream-Sicherheitsfixes lassen sich nicht mergen — kein gemeinsamer Vorfahre
Adoptiert aus threadnet-web#12 (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei.
Am 2026-08-06 gemessen (docs/axion1337-fork.md, Abschnitt 4): Dieses Repo hat keine Upstream-Historie. Element Web 1.12.17 kam am 2026-05-10 als kompletter Baum herein — in 3da3635, im selben Commit wie das erste eigene Feature.
Damit gibt es keinen gemeinsamen Vorfahren mit element-hq/element-web. git merge upstream/develop ist nicht möglich; erzwungen kollidiert praktisch jede Datei.
Warum das ein Sicherheitsthema ist, kein Build-Thema
Element veröffentlicht Sicherheitsfixes als neue Version. Bei einem normalen Fork zieht man sie mit einem Merge. Bei uns bedeutet dasselbe: neuen Upstream-Stand beschaffen und unsere 12 Patches von Hand neu auftragen — davon sieben in der Medien-Pipeline, wo Element gerade auf MVVM umbaut.
Das ergibt eine unangenehme Kette mit gitops#22 (Advisory-Monitoring): Wir würden von einer Lücke erfahren und wären trotzdem langsam. Die Zeitspanne zwischen „bekannt" und „gepatcht" ist das, was zählt — und sie ist hier strukturell zu lang.
⚠️ Verschärfend: Verschiebt Element beim MVVM-Umbau eine der viewmodels/-Dateien, entsteht kein Konflikt — unsere Zeilen sind schlicht weg, und Git meldet nichts.
Was zu tun ist
- Zuerst messen, nicht bauen: Auf welchem Stand ist Upstream inzwischen, und sind seit 1.12.17 Sicherheitsfixes für Element Web erschienen? Das beantwortet, ob das dringend ist oder Vorsorge.
element-hq/element-webals zweiten Remote aufnehmen und den Tag von 1.12.17 holen. Damit lässt sich ein Update wenigstens als Diff betrachten, statt blind zu kopieren.- Prüfen, ob sich ein gemeinsamer Vorfahre nachträglich herstellen lässt — ein Graft/Replace des Import-Commits auf den passenden Upstream-Tag. Wenn das trägt, sind künftige Updates wieder ein Merge.
- Falls nicht: einen Ablauf schreiben, wie unsere 12 Patches auf einen neuen Stand aufgetragen werden — mit dem Funktionstest für ClamAV als Abnahme (verschlüsselte Datei senden, abgelehnte empfangen).
Zusammenhang: gitops#22 (Advisory-Monitoring) ist die Erkennung, dieses Issue die Reaktionsfähigkeit. Das eine nützt wenig ohne das andere.
Gefunden am 2026-08-06 beim Vermessen der Merge-Reibung (Arbeitspaket 3 aus #7).
Schritt 1 beantwortet 2026-08-19 — es ist keine Vorsorge mehr
Das Issue verlangt ausdrücklich „zuerst messen, nicht bauen". Gemessen:
Wir sind neun Veröffentlichungen zurück. Import war Element Web 1.12.17 (2026-05-10); Upstream steht bei v1.12.26 (2026-08-18).
Und es gibt eine offene Sicherheitsmeldung, die uns betrifft:
| Advisory | GHSA-wrcp-5v3v-3j6v |
| veröffentlicht | 2026-07-20 (vier Wochen offen) |
| Einstufung | medium |
| Inhalt | Ein bösartiger Homeserver kann über die Startseite HTML in Element Web einschleusen |
| betroffen | < v1.12.22 — wir laufen 1.12.17 |
Die übrigen fünf Advisories im Projekt betreffen ältere Stände (≤ 1.11.x) und damit nicht uns.
Einordnung — real, aber schmal
Der Angriff setzt voraus, dass der Client auf einen bösartigen Homeserver zeigt. Unsere Nutzer verwenden ihn gegen den eigenen Server, und Föderation ist seit ADR-0021 geschlossen.
Aber die Voraussetzung ist erreichbar: disable_custom_urls ist in
element-values.yaml nicht gesetzt, Element erlaubt damit standardmäßig die
Eingabe eines beliebigen Homeservers — und die Desktop-Builds werden verteilt. Wer
sich mit unserem Client woanders anmeldet, ist ungeschützt.
Was daraus folgt
Die Antwort auf „dringend oder Vorsorge" lautet: weder Panik noch Vorsorge, sondern überfällig. Ein Fork ohne Merge-Weg hat vier Wochen gebraucht, um eine bekannte Lücke nicht zu schließen — genau die Zeitspanne, die dieses Issue als das eigentliche Problem benennt.
Sofort möglich, unabhängig vom Merge-Problem: disable_custom_urls: true setzen.
Das nimmt dem Advisory für unsere Nutzer die Voraussetzung, kostet eine Zeile und
berührt die Fork-Frage nicht. Ob fremde Homeserver überhaupt erlaubt sein sollen, ist
ohnehin eine eigene Entscheidung — bei geschlossener Föderation liegt „nein" nahe.
Schritte 2–4 (Upstream als Remote, Graft-Versuch, Patch-Auftragsverfahren) bleiben offen; sie sind der eigentliche Umfang dieses Issues.
Teilmaßnahme 2026-08-19 — disable_custom_urls an beiden Stellen
Entscheidung sorb. Gesetzt in zwei Dateien, nicht in einer:
| Ort | Datei | Commit | wirksam |
|---|---|---|---|
| Web-Client | gitops:apps/production/custom-configs/element-values.yaml |
d809b3f |
mit dem Flux-Abgleich (Element liest config.json beim Laden) |
| Desktop-Client | ThreadNet-Web:apps/desktop/axion1337/config.json |
e1e9a19 |
erst mit dem nächsten Desktop-Build |
Die zweite Stelle wäre fast durchgerutscht: Der Desktop-Client lädt seine eigene
config.json, nicht die des Web-Deployments — derselbe Fallstrick wie beim
Themes-Rollout. Eine Änderung nur in element-values.yaml hätte den Web-Client
abgesichert und genau die Builds unberührt gelassen, die verteilt werden.
Was sie bewirkt — und was nicht
Im Code unserer Fassung nachgelesen, nicht angenommen:
ServerPicker.tsx: Der „Bearbeiten"-Knopf am Servernamen wird nicht gerendert. Über die Oberfläche ist der Homeserver damit nicht mehr wechselbar.ErrorUtils.tsx: Bei 401/403 benennt die Fehlermeldung den Server, statt generisch zu bleiben — kleiner Nebengewinn für den Alltag.
⚠️ Es ist eine Oberflächen-Sperre, keine technische. MatrixChat.tsx übernimmt
hs_url weiterhin aus der URL — in zwei Registrierungs-Flüssen (mobile Registrierung,
Bestätigungslink) und ohne disable_custom_urls zu prüfen. Ein präparierter Link
bleibt davon unberührt.
Für GHSA-wrcp-5v3v-3j6v heißt das: Der bequeme, sichtbare Weg zu einem fremden
Homeserver ist weg, alle Wege sind es nicht. Die Maßnahme senkt die Wahrscheinlichkeit,
dass jemand versehentlich oder auf Zuruf woanders landet — sie ist kein Ersatz für
das Upstream-Update. Das bleibt Schritt 2–4 dieses Issues.
Schritt 2 erledigt 2026-08-19 — und er widerlegt eine Annahme des Issues
upstream (element-hq/element-web) ist als zweiter Remote eingerichtet, v1.12.17
und v1.12.26 sind flach geholt. Der Remote ist lokale Konfiguration und wird
nicht mitcommittet; die Einrichtung steht jetzt in
ThreadNet-Web:docs/axion1337-fork.md (Commit fa5dcc5).
Der Import ist NICHT der Tag v1.12.17
Das Issue und die Fork-Doku behaupteten beide, „Element Web 1.12.17 kam am 2026-05-10 als kompletter Baum herein". Die erste Messung mit dem neuen Remote widerspricht dem:
| Messung | Ergebnis |
|---|---|
git diff --stat v1.12.17 3da3635 |
783 Dateien, +17443 / −10371 |
| nur bei uns vorhanden | 115 Dateien |
| nur im Tag vorhanden | 62 Dateien |
Entscheidend sind zwei davon, weil sie datieren:
apps/web/src/viewmodels/room/timeline/event-tile/body/TextualBodyViewModel.tsx und
packages/shared-components/src/core/roving/RovingTabIndex.tsx — im Tag v1.12.17
nicht vorhanden, in v1.12.26 und in unserem Import vorhanden. Der
CHANGELOG.md unseres Imports endet bei 1.12.17 (2026-04-30), weil er erst beim
Release fortgeschrieben wird.
Die Grundlage ist also ein develop-Stand nach dem 1.12.17-Release (1.12.18 kam am
2026-05-12), nicht der Tag. Ausgerechnet MVVM-Dateien belegen es — der Bereich, vor dem
dieses Issue ohnehin warnt.
Folge für Schritt 3
Ein Graft auf v1.12.17 wäre falsch. Er würde jede künftige Zusammenführung auf
eine erfundene Ahnenreihe stellen und Konflikte an Stellen erzeugen, wo keine sind —
oder schlimmer: keine erzeugen, wo welche gehören. Wer den gemeinsamen Vorfahren
nachträglich herstellen will, muss den passenden develop-Commit finden. Das
braucht die volle Upstream-Historie; ein flacher Tag-Fetch reicht dafür nicht.
Schritt 3 bleibt damit offen, aber er hat jetzt eine tragfähige Fragestellung statt einer falschen Zielmarke.
Unverändert: die Advisory-Bewertung
Der Basisstand liegt zwischen 1.12.17 und 1.12.18 und damit klar unter 1.12.22 —
GHSA-wrcp-5v3v-3j6v trifft uns weiterhin. Die Korrektur ändert die Dringlichkeit
nicht, nur den Weg dorthin.
Schritt 3 beantwortet 2026-08-19 — der Graft trägt, und er halbiert das Problem
Volle Upstream-Historie geholt (70.330 Commits, .git wächst von 87 MB auf 603 MB).
Damit ließ sich der gesuchte gemeinsame Vorfahre suchen statt raten.
Die Basis ist deadd548 vom 2026-05-08
Verfahren: für jeden develop-Commit im Fenster 25.04.–16.05. die Zahl der gegen
unseren Import abweichenden Dateien messen — der Basis-Commit ist das Minimum. Gemessen
wurde der Baum, nicht das Datum.
Ergebnis: deadd548 („Update storybook", #33437) mit 43 abweichenden Dateien —
gegenüber 783 beim fälschlich angenommenen Tag v1.12.17. Und diese 43 zerfallen
sauber:
| Art | Anzahl | Was es ist |
|---|---|---|
| nur Modus (755 → 644) | 31 | der Import-Bug, den die Fork-Doku als historisch beschreibt |
| echte Inhaltsänderung | 12 | davon 5 + 1 Test = unser Discord-Feature, dazu LICENSE und CHANGELOG.md |
| Hinzufügungen | 2 | unsere Feature-Dateien |
Der inhaltliche Rest ist also genau das, was wir damals selbst geändert haben. Damit
ist deadd548 der Stand, aus dem der Fork genommen wurde.
Der Graft wurde getestet, nicht behauptet
In einem Wegwerf-Klon (Produktions-Repo unberührt, danach entfernt):
| vor dem Graft | git merge-base main upstream/develop → leer |
nach git replace --graft 3da3635 deadd548 |
gemeinsamer Vorfahre deadd548 |
git merge upstream/develop |
läuft durch, 32 konfliktbehaftete Dateien |
⚠️ Ein Zwischenergebnis war wertlos und wäre fast als Erfolg durchgegangen: Der erste
Merge-Versuch gegen v1.12.26 meldete „0 Konflikte" — er war aber gar nicht
gelaufen („refusing to merge unrelated histories"), weil der Tag flach geholt war und
nur einen einzigen Commit trägt. Erst die Gegenprobe auf MERGE_HEAD deckte das auf.
Was die 32 Konflikte sind
Nur vier sind Quellcode — und es sind genau unsere Patches:
MImageBody.tsx, MAudioBody.tsx (ClamAV), SdkConfig.ts (Branding),
RoomListItemViewModel.ts (Discord-Feature). Der Rest sind
.github/workflows/* (die Fork-Doku führt sie als „gering — eigene Strecke") und
pnpm-lock.yaml, das ohnehin regeneriert wird.
Was das ändert
Aus „neuen Upstream-Baum beschaffen und zwölf Patches von Hand neu auftragen" wird „vier Quellcode-Konflikte in einem normalen Drei-Wege-Merge lösen".
Wichtiger noch ist die stille Gefahr, die verschwindet. Das Issue warnt: „Verschiebt
Element beim MVVM-Umbau eine der viewmodels/-Dateien, entsteht kein Konflikt — unsere
Zeilen sind schlicht weg, und Git meldet nichts." Mit echtem gemeinsamem Vorfahren
meldet Git es. Das ist der eigentliche Gewinn, nicht die Zahl.
Entscheidung, die noch aussteht
Der Graft ist eine lokale Ersetzung (refs/replace/*). Damit alle davon haben,
müsste er mitgeliefert werden — git push origin 'refs/replace/*' und ein Hinweis in
der Doku, dass Klone git fetch origin 'refs/replace/*:refs/replace/*' brauchen.
Alternative: kein Graft, sondern beim nächsten Update einmalig einen echten
Merge-Commit mit --allow-unrelated-histories bauen und ab dann normal weitermergen.
Beides ändert die Historie-Wahrnehmung des Repos dauerhaft und ist damit ADR-pflichtig. Entscheidung sorb steht aus; Schritt 4 (Auftragsverfahren für die Patches) wird bei Weg 1 oder 2 weitgehend gegenstandslos.