Der umfassende Leitfaden zur Verwaltung von Ruby-Gem-Abhängigkeiten
5. August 2022
0 Min. LesezeitRuby verfügt, wie andere Programmiersprachen auch, über ein ganzes Ökosystem aus Open-Source-Bibliotheken von Drittanbietern, die als Gems oder manchmal als Ruby-Gems bezeichnet werden. Diese Gems werden von der Community entwickelt und sind auf RubyGems.org verfügbar, der offiziellen Registry für Ruby-Bibliotheken. Wie in anderen Open-Source-Ökosystemen können Bedrohungsakteure gezielt Schadcode veröffentlichen oder Code, der Hintertüren oder das Abgreifen von Zugangsdaten enthält. Daher ist es entscheidend, Ruby-Gems aus dem Open-Source-Bereich sorgfältig zu verwalten und zu überprüfen.
In diesem Artikel gehe ich die Konzepte und Tools des Ruby-Abhängigkeitsökosystems durch und beantworte einige häufig gestellte Fragen von Ruby-Entwicklerinnen und -Entwicklern.
Die Programmiersprache Ruby
Vielleicht haben Sie schon von Ruby on Rails (RoR) gehört, dem beliebten Webentwicklungs-Framework, das maßgeblich zum Erfolg und zur Popularität von Ruby beigetragen hat. RoR basiert auf Ruby, einer dynamischen, plattformübergreifenden und interpretierten Sprache. Ruby-Quelldateien sind leicht an der Dateiendung .rb zu erkennen.
Was sind Ruby-Gems?
Gems sind paketierte Quellcode-Bibliotheken, die modular und unabhängig sind und sich problemlos in verschiedenen Projekten wiederverwenden lassen.
Was ist RubyGems und wie unterscheidet es sich von Bundler?
RubyGems ist die zentrale Paket-Registry, in der Ruby-Gems von Drittanbietern aus dem Open-Source-Bereich bereitgestellt werden. Außerdem ist es der offizielle Paketmanager für Ruby, der bei der Verwendung über die Befehlszeile als gem bezeichnet wird.

RubyGems ermöglicht Entwicklerinnen und Entwicklern auf hervorragende Weise den Zugriff auf ein Ökosystem mit Hunderttausenden von Open-Source-Bibliotheken, die sie in ihren Projekten einsetzen können.
Die gems-CLI von RubyGems ist in einer funktionierenden Ruby-Umgebung bereits vorinstalliert. So können Entwicklerinnen und Entwickler direkt ihre bevorzugten Open-Source-Abhängigkeiten installieren. Zum Beispiel:
Die gems-CLI verwaltet Abhängigkeiten jedoch einzeln: Sie ruft sie aus einer Registry ab und installiert sie im Dateisystem, sodass sie verfügbar sind und sich problemlos in Ruby-Codeprojekten importieren lassen.
Das Bundler-Projekt ist technisch gesehen selbst ein Ruby-Gem und wird auch als solches installiert. Es vereinfacht die Installation von Gems und ermöglicht mithilfe einer Manifestdatei namens Gemfile sowie der zugehörigen Lockdatei Gemfile.lock einen deterministischen und konsistenten Abhängigkeitsbaum. Letztere legt die Abhängigkeiten im gesamten Baum fest und sorgt dafür, dass Installationen auch langfristig konsistent bleiben.
Da Bundler ein Gem ist, können Sie ganz einfach damit beginnen:
Mit diesem Befehl steht Entwicklerinnen und Entwicklern das Befehlszeilentool bundler zur Verfügung.
Das Ruby-Gemfile
Die Datei Gemfile ist eine Manifest-Textdatei, in der alle Abhängigkeiten des Projekts sowie weitere Metadaten-Anweisungen beschrieben sind, die das Tool bundler bereitstellt.
Ein einfaches Gemfile sieht so aus:
Das obige Gemfile definiert den Eintrag source, also das Remote-Repository, aus dem Bundler alle Gems herunterlädt. Jede Zeile mit gem definiert eine Open-Source-Bibliothek, die abzurufende Version sowie die Quelle, aus der sie bezogen werden soll.
Das folgende komplexere Beispiel zeigt, wie Ruby-Gems aus verschiedenen Quellen bezogen werden:
Weitere Informationen zu diesen Quellen finden Sie ausführlich in der offiziellen Git-Dokumentation von Bundler.
Woraus besteht ein Ruby-Gem?
Ein Ruby-Gem ist Ruby-Quellcode in paketierter, modularer Form, der von anderen Ruby-Gems, Ruby-Anwendungen oder allgemein von Nutzerinnen und Nutzern wiederverwendet werden kann, die wie im Beispiel zu Bundler weiter oben über die Befehlszeile damit interagieren.
Ruby-Gems folgen üblicherweise einer Konvention, die Ruby-Quellcode, Tests, möglicherweise ausführbare Dateien im Dateipfad der Nutzerinnen und Nutzer und vor allem eine Spezifikationsdatei für Ruby-Gems umfasst, die als Gemspec bezeichnet wird.
Einige Verzeichnisse wie test/ und bin/ sind relativ selbsterklärend: Sie enthalten den Testcode für diese Abhängigkeit und die ausführbare Datei, die mit ihr ausgeliefert und installiert wird. Weitere wichtige Dateien sind Gemfile und Gemfile.lock. Sie haben wir bereits im Zusammenhang mit Bundler kennengelernt, mit dem Ruby-Gems verwaltet werden. Die Lockdatei sorgt dafür, dass Installationen deterministisch und zuverlässig wiederholbar sind.
Die Datei Rakefile gehört zum Open-Source-Projekt Rake, einem Make-ähnlichen Build-Tool für Ruby-Projekte. Daher ähnelt der Name dem von Makefile. Hier ein Beispiel für den Inhalt:
Die Rakefile importiert die benötigten Klassen aus dem Rake-Gem und definiert eine test-Aufgabe. Wird der Befehl rake test in diesem Verzeichnis ausgeführt, weist er das Programm Rake an, mithilfe eines Glob-Musters alle Testdateien im Ordner test/ zu finden und anschließend auszuführen. Weitere Informationen zum Format der Rakefile finden Sie in der Dokumentation des Rake-Projekt-Repositorys.
Eine weitere neue Datei, die Ihnen möglicherweise im obigen Dateibaum aufgefallen ist, ist die Datei gemspec. Sie trägt oft denselben Namen wie das Paket, zum Beispiel base64ness.gemspec. Die gemspec beschreibt das Ruby-Gem und stellt Metadaten zu dieser Abhängigkeit bereit. Die RubyGems-Registry kann diese Informationen damit erfassen und analysieren und Nutzerinnen und Nutzern anzeigen, die nach Ruby-Gems suchen.
Hier ein Beispiel für das oben erwähnte Ruby-Gem base64 base64ness.gemspec:
Auf der RubyGems-Website finden Sie eine vollständige Dokumentation zur Specification-Klasse, auf die wir oben Bezug genommen haben. Sie enthält weitere Metadaten zu einem Ruby-Gem, erweiterte Funktionen, mit denen Ruby-Maintainer ausführbare Dateien definieren können, sowie die Möglichkeit, C-Erweiterungen in Ruby-Gems zu bündeln, um durch Cross-Compilation native Module bereitzustellen und vieles mehr.
Tipp: Wenn Sie wissen möchten, was sich in einem bestimmten Ruby-Gem befindet, können Sie es in ein Verzeichnis entpacken und den Quellcode wie folgt untersuchen:
Die Installation von Ruby-Gem-Abhängigkeiten steuern
Abhängigkeiten lassen sich logisch in bestimmte Kategorien gruppieren. Beispielsweise können Sie Ruby-Gem-Abhängigkeiten für die Produktion sowie Entwicklungs-Gems haben, die Sie nur bei der lokalen Entwicklung installieren.
Um zwischen ihnen zu unterscheiden, können Sie das folgende Gemfile-Manifest definieren:
Anschließend können Sie Abhängigkeiten mit Bundler nach Kategorie installieren. Der folgende Befehl installiert beispielsweise nur Produktions-Abhängigkeiten:
Warum benötigen wir eine Gemfile.lock?
Wenn Sie Abhängigkeiten ausschließlich im Paketmanifest Gemfile von Bundler definieren könnten, wären Sie mit den folgenden Einschränkungen konfrontiert:
Es werden nur direkte Ruby-Gem-Abhängigkeiten dokumentiert.
Für diese direkten Ruby-Gem-Abhängigkeiten wird eine ungenaue und locker definierte Paketversion angegeben. Dabei kann es sich um die neueste Version oder lediglich um die neueste Version innerhalb eines semantischen Versionsbereichs handeln.
Selbst wenn Sie diese direkten Ruby-Gem-Abhängigkeiten auf feste Versionen festlegen, kann bei jeder neuen Installation dennoch eine unerwartete Version eines abhängigen Gems aufgelöst werden.
Daraus folgt: Ohne eine Lockdatei, die den gesamten verschachtelten Abhängigkeitsbaum der für Ihr Projekt installierten Ruby-Gems festlegt, würden unvorhersehbare Versionen installiert. Das ist vermutlich das Letzte, was Sie in einer automatisierten CI- oder Build-Umgebung oder bei anderen Ruby-Entwicklerinnen und -Entwicklern möchten, die mit Ihnen am Projekt arbeiten.
Deshalb gibt es die Gemfile.lock:
Sehen wir uns die Spezifikation und das Format dieser Lockdatei für Gem-Abhängigkeiten an:
Die Direktive
GEMleitet den Abschnitt ein, in dem alle Ruby-Gem-Abhängigkeiten in einem verschachtelten Baumformat aufgeführt werden. Darin sind direkte und transitive Abhängigkeiten sowie ihre Versionen zu sehen. Sie werden unter der Direktivespecsaufgeführt. Die Direktiveremotegibt dem Bundler-Tool an, aus welcher Quelle diese Ruby-Gems für die Installation bezogen werden sollen.Die Direktive
PLATFORMSenthält eine offene Liste der Zielplattformen, für die native Ruby-Gems erstellt werden müssen, beispielsweise aufgrund der für in C geschriebenen Ruby-Erweiterungen erforderlichen Cross-Compilation-Kette.Die Direktive
RUBY VERSIONist optional und gibt die Ruby-Runtime-Version an, die beim Erstellen dieser LockdateiGemfile.lockverwendet wurde.Die Direktive
BUNDLED WITHgibt die Bundler-Version an, mit der die Lockdatei erstellt wurde. Entwicklerinnen und Entwickler mit älteren Versionen sollten ein Upgrade in Betracht ziehen, um auf dem neuesten Stand zu bleiben und konsistente, zuverlässige Ergebnisse bei der Installation von Ruby-Gems zu erzielen.
bundler-audit und warum die Sicherheit von Ruby-Gems verbessert werden muss
Ein großartiges Ökosystem bringt große Verantwortung mit sich. Ganz genau. Hier kommt das von der Community getragene Projekt bundler-audit ins Spiel. Es ist ein Ruby-Gem, das die in der Lockdatei des Projekts (Gemfile.lock) aufgeführten Abhängigkeiten scannt und mit einer Datenbank anfälliger Ruby-Gems vergleicht. So meldet es Versionen, bei denen eine oder mehrere Sicherheitslücken gefunden wurden.
Erste Schritte mit bundler-audit zum Scannen nach Sicherheitslücken in Ruby-Gems
Um mit bundler-audit nach Sicherheitslücken zu suchen, installieren wir es zunächst wie jedes andere Ruby-Gem:
Nach der Installation muss bundler-audit Sicherheitshinweise aus Quellen wie der von der Community gepflegten ruby-adivsory-db herunterladen. Diese bezieht ihre Daten wiederum aus GitHub Advisory und der von Google gepflegten Open-Source-Datenbank für Sicherheitslücken:
Bei erfolgreicher Ausführung sollte der Befehl bundler-audit eine ähnliche Ausgabe wie die folgende anzeigen, die bestätigt, dass alles auf dem neuesten Stand ist:
Anschließend können wir bundle-audit ohne zusätzliche Argumente ausführen und nach Sicherheitslücken suchen. Für mein lokales Ruby-on-Rails-Projekt wurde derzeit Folgendes ausgegeben:
Das sieht gut aus, kann aber irreführend sein und Sie unnötigen Risiken aussetzen. Tatsächlich handelt es sich um einen falsch negativen Befund, denn für einige der von mir installierten Abhängigkeitsversionen gibt es durchaus Sicherheitslücken.
Bei allem Respekt für die Arbeit der Community am Aufbau von Sicherheitstools: Wahrscheinlich fehlen ihr die Mitarbeitenden und Ressourcen, um eine angemessene Abdeckung von Sicherheitslücken zu gewährleisten. Hier kommt der Sicherheitsscanner von Snyk Open Source ins Spiel.
Snyk bietet ein kostenloses CLI-Tool, das von einem auf Entwicklerinnen und Entwickler ausgerichteten Sicherheitsunternehmen mit einer umfangreichen Datenbank mit Berichten zu Sicherheitslücken in Ruby-Gems unterstützt wird. Sie können es installieren und Ihre Abhängigkeiten scannen.
Ruby-Gems kostenlos mit Snyk absichern
Testen wir Snyk einmal und sehen wir, welche Sicherheitslücken es in unserem Rails-Projekt findet. Wenn Sie wie ich ein M1 MacBook Pro verwenden, führen Sie Folgendes aus:
Dadurch wird die eigenständige Snyk-Binärdatei heruntergeladen, ausführbar gemacht und in Ihrem Pfad verfügbar gemacht. Falls Sie eine andere Installationsmethode benötigen, etwa brew für macOS oder scoop für Windows, lesen Sie die Dokumentation zu den ersten Schritten mit der Snyk-CLI.
Sobald die Snyk-CLI installiert ist, können wir sie wie folgt ausführen:
Bei der ersten Verwendung wird folgende Meldung angezeigt:
Geben Sie anschließend snyk auth ein und folgen Sie den Anweisungen: Kopieren Sie eine Authentifizierungs-URL in den Browser und melden Sie sich an oder registrieren Sie sich, um Ihren API-Schlüssel zu erhalten. Schon nach kurzer Zeit kehren Sie zur Eingabeaufforderung zurück und können mit dem Scan fortfahren:
Nun denn: 2 Probleme und 59 anfällige Pfade … offenbar sind wir nicht so sicher, wie wir dachten. Im Moment gibt es anscheinend keine neueren Versionen, auf die sich diese Bibliotheken im verschachtelten Abhängigkeitsbaum aktualisieren ließen. Damit Snyk die Gemfile unseres Projekts fortlaufend überwacht und nach neuen Versionen mit Korrekturen sucht, können wir eine der folgenden Maßnahmen ergreifen:
Gehen Sie zu https://apps.snyk.io und verbinden Sie Snyk mit dem Quellcode-Repository auf GitHub oder einer anderen Plattform. So kann Snyk dieses Projekt im Hintergrund überwachen.
Führen Sie den Befehl
snyk monitoraus. Dabei werden Momentaufnahmen der aktuellen DateienGemfileundGemfile.lockerstellt und kontinuierlich überwacht. Beachten Sie, dass Sie den Befehl in einer CI-Umgebung oder einem automatisierten Build ausführen müssen, damit jedes Mal, wenn diese Ruby-Paketmanifestdateien aktualisiert werden, eine neue Momentaufnahme zur Überwachung an Snyk gesendet wird.
Sollte ich bundle-audit oder Snyk verwenden?
Verwenden Sie beide. Das ist keine diplomatische Aussage, sondern sie ergänzen sich tatsächlich auf folgende Weise:
Snyk bietet eine umfangreiche Datenbank mit Sicherheitslücken im Ruby-Ökosystem, die manuell kuratiert und stets aktuell gehalten wird – oft sogar früher als bei bundle-audit und anderen.
Bundle-audit führt neben dem Scannen auf Sicherheitslücken weitere Prüfungen durch. So wird beispielsweise überprüft, ob Ihre Ruby-Gems nicht von unsicheren Quellen wie
http://undgit://abgerufen werden. Andernfalls könnten Man-in-the-Middle-Angriffe oder Lockfile-Injection-Angriffe den Quellcode manipulieren, den Sie erhalten und ausführen.
Zusammenfassung
Wir haben uns mit der Verwaltung von Ruby-Gems als Projektabhängigkeiten befasst, erläutert, warum die Verwendung einer Lockfile wichtig ist, und weitere Aspekte sowie empfohlene Best Practices behandelt – etwa Ruby-Abhängigkeiten sicher zu nutzen, indem Sie sie mit Tools wie Snyk und bundler-audit scannen.
Weitere Ruby-Ressourcen:
Wenn Sie auch JavaScript entwickeln, empfehle ich Ihnen wärmstens, Was ist package-lock.json und wie funktioniert eine Lockfile für Yarn- und npm-Pakete? zu lesen.
Starten Sie mit Capture-the-Flag
Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Challenges lösen.



