Liebes GitHub,
Also, die Sache ist die: Es gibt ein Sicherheitsproblem, das schon länger ein offenes Geheimnis ist. Man spricht darüber in Issue-Trackern. Es taucht in Sicherheitsveröffentlichungen auf. Es wird in Slack-Threads diskutiert, die unweigerlich enden mit „...aber wir bräuchten GitHub, um diese Daten tatsächlich offenzulegen.“
Ich mache Sie darauf aufmerksam, weil ich es leid bin zu sehen, wie diese Diskussion immer auf die gleiche Weise endet. Die Sicherheits-Community bittet lediglich um Einblick in Daten, die Sie bereits besitzen. Ohne diese stecken wir fest. Paket-Registries können Benutzer nicht warnen. Sicherheitstools können verdächtige Referenzen nicht kennzeichnen. Angreifer hingegen verstehen diesen blinden Fleck perfekt. Sie nutzen ihn bereits aus, genau wie Shai Hulud es tat.
Die Feiertage stehen bevor. Ich denke, ich habe mich dieses Jahr gut geschlagen. Mein einziger Wunsch ist, dass Sie uns die Werkzeuge bereitstellen, um das Ökosystem besser zu schützen. Ich hoffe, das ist nicht zu viel verlangt!
Wo liegt das Problem?
Paketmanager wie Ihr eigenes npm sowie Drittanbieter wie Bun und PyPI ermöglichen es Entwickelnden, ein GitHub-Repository direkt als Abhängigkeit zu installieren. Ihre eigenen GitHub Actions basieren auf diesem gleichen Primitiv.
npm install github:trusted-org/trusted-package#commit-sha
bun install github:trusted-org/trusted-package#commit-sha
pip install git+https://github.com/trusted-org/trusted-package#commit- uses: trusted-org/trusted-package@commit-shaDie meisten Leute würden dies sehen und denken: „Wo ist das Sicherheitsproblem? Ich gebe doch das exakte Repository an.“
Ja. Das dachte ich auch.
Aber Folgendes passiert: Wenn dieser Commit-SHA in einem Fork des Repositorys existiert, ziehen Sie Code aus dem Fork. Nicht aus dem Repository in Ihrer URL. Aus dem Fork. Was zum Teufel?
Lassen Sie das einen Moment sacken. Ich warte…. Die URL besagt trusted-org/trusted-package. Aber wenn ein Angreifer dieses Repo geforkt, einen bösartigen Commit hinzugefügt und Sie dazu gebracht hat, den SHA dieses Commits zu referenzieren, haben Sie gerade deren Code installiert. Nicht den Code, den Sie dachten. Nicht das Repo, das Sie angegeben haben. Sondern deren.
Warum passiert das?
Dies geschieht aufgrund von GitHubs „Fork Network“.
Wahrscheinlich haben Sie noch nie davon gehört. Hier ist der Punkt: Wenn Sie ein Repository forken, erhalten Sie keine vollständig unabhängige Kopie. Ihr Fork tritt einem Netzwerk bei und teilt den zugrunde liegenden Git-Objektspeicher mit dem Original und jedem anderen Fork. So handhabt GitHub Skalierung. Sie speichern nicht eine Million Kopien derselben Commits. Das macht Sinn.
Das ist auch der Grund, warum dieser Angriff funktioniert.
Die oben genannten Befehle erreichen letztendlich GitHubs „Ein Repository-Archiv (tar) herunterladen“-Endpoint. Die Dokumentation sagt Folgendes über den owner Parameter:

Es gibt keine Garantie, dass der Code direkt zum Repository gehört, oder Warnungen davor, dass er möglicherweise von einem Fork stammt. Ehrlich gesagt? Angesichts der Architektur ist dieses Verhalten sinnvoll. Der Commit existiert im gemeinsamen Graphen. GitHub liefert ihn aus. Das ist nicht falsch.
Was ist ein Problem ist, dass dies eine Mehrdeutigkeit schafft, die niemand sonst durchschauen kann. Sie fragen nach trusted-org. Sie erhalten Code vom Angreifer. GitHub hat Ihre Anfrage erfüllt. Sie haben nur nicht das bekommen, wonach Sie dachten, Sie gefragt zu haben. Und kein Tool außerhalb von GitHub kann den Unterschied erkennen.
Die Asymmetrie
Wir haben es wirklich geschätzt, als Sie das Warnbanner auf GitHub.com hinzugefügt haben. Eine Warnung für solche Commits zu sehen? Das ist nützlich. Es zeigt, dass Sie wissen, dass dies ein Problem ist, das es wert ist, sichtbar gemacht zu werden.

Aber die Sache ist die: Paketmanager schauen nicht auf Ihre Website. Sie rufen Ihre API auf. Und die API gibt ihnen keinerlei Hinweis darauf, dass etwas Ungewöhnliches vor sich geht. Kein Flag, keine Metadaten, nichts dokumentiert. Daher können npm, PyPI und Bun keine Benutzer warnen. Die Informationen existieren. Sie stellen sie bereits im Frontend dar. Aber das Ökosystem kann nicht darauf zugreifen.
Warum nicht?
Zeit, streng zu werden
Erinnern Sie sich an den „Download a repository archive (tar)“-Endpunkt, über den wir gesprochen haben? Im Moment ist er das schwächste Glied. Aber er ist auch der offensichtliche Ort, um dies zu beheben.
Hier ist eine Idee: Fügen Sie einen streng Parameter. Wenn er gesetzt ist, schlägt die Anfrage fehl, falls der Commit nur in einem Fork existiert und nicht im tatsächlich angegebenen Repository. Paketmanager können sich dafür entscheiden, alle anderen behalten das aktuelle Verhalten bei, nichts geht kaputt.
Sie führen diese Prüfung bereits im Frontend für das Warnbanner durch. Geben Sie der API einfach die gleiche Fähigkeit. Natürlich wäre es ideal, wenn Sie generell mehr Fork-Netzwerkinformationen in Ihrer API verfügbar machen könnten, aber dies löst zumindest das offensichtlichste Problem.
Frohe Feiertage!
Ich schreibe dies nicht als Beschwerde. Ich schreibe, weil wir alle das gleiche Ziel verfolgen: ein sicheres und zuverlässiges Ökosystem. Sie haben das Problem bereits anerkannt, indem Sie die Warnung auf GitHub.com angezeigt haben. Nun würde es einen großen Unterschied machen, dasselbe Signal über die API verfügbar zu machen, damit das Ökosystem darauf reagieren kann.
Eine kleine Verbesserung Ihrerseits würde eine erhebliche Verbesserung im gesamten Ökosystem ermöglichen. Ist das nicht die beste Art von Verbesserung?
Und da gerade die Feiertage sind, möchte ich etwas teilen, das ich hinter den Kulissen gehört habe. In den letzten Wochen habe ich mit einigen der größeren Akteure im Ökosystem gesprochen, und es gibt eine leise, gemeinsame Sorge, dass etwas schiefgehen könnte, während alle versuchen, sich eine Auszeit zu nehmen, um Zeit mit ihren Liebsten zu verbringen. Die Behebung dieses einen Problems wird dieses Risiko natürlich nicht beseitigen, aber die Besorgnis ist real und weit verbreitet.
Frohe Feiertage, GitHub. Auf ein ruhiges Jahresende.

