Ein Scan, dann ein Pull Request

Scandar schreibt nicht auf den Standard-Branch. Der Fix bleibt auf scandar/fix-…, bis du ihn mergst.

Was ein Scan macht

  1. Melde dich mit der GitHub App an. Sichtbar sind nur die bei der Installation gewählten Repositories.
  2. Projekte finden: eine package.json neben package-lock.json, pnpm-lock.yaml oder yarn.lock. Verschachtelte Manifeste ohne eigene Lockfile zählen als Workspace-Mitglieder.
  3. Lockfile lesen und OSV.dev abfragen. Doppelte Advisory-IDs werden zusammengeführt.
  4. Fix-Plan erstellen. Direkte Abhängigkeiten wechseln zu ^fixed. Transitive werden mit Overrides, pnpm.overrides oder pnpm-workspace.yaml oder Yarn-resolutions gepinnt.
  5. Lockfile in einem temporären Verzeichnis mit deaktivierten Paket-Skripten neu erzeugen, dann Branch und Pull Request öffnen.

Du kannst einzelne Pakete auswählen. Major-Sprünge sind anfangs abgewählt. Auf einem Projekt können mehrere Pull Requests offen sein, und dasselbe Paket wird nicht zweimal gepatcht.

Sicherere Fix-Pull-Requests

Ein Fix schlägt kein Release vor, das vor weniger Tagen veröffentlicht wurde als deine Versionsverzögerung. Standard sind 5 Tage. Stelle sie unter Einstellungen → Pull Requests ein oder überschreibe sie für ein Projekt. 0 deaktiviert die Verzögerung. Das Maximum sind 90 Tage.

Scandar liest den Veröffentlichungszeitpunkt jeder npm-Version und prüft die Version, die wirklich in der Lockfile landet. Ein Bereich, der auf ein jüngeres Release rutschen würde, wird auf die zulässige Version gepinnt. Gibt es noch nichts Altes genug, wird der Fix verschoben, und die Seite zeigt, wann er verwendbar wird. Eine kritische Advisory, eine bekannte ausgenutzte Schwachstelle oder ein bösartiges Paket wird trotzdem vorgeschlagen, mit dem Hinweis, dass die Version neu ist.

Akzeptiert package.json die behobene Version bereits, ändert sich nur die Lockfile. npm nutzt npm update --min-release-age, pnpm nutzt minimumReleaseAge. Yarn 1 hat kein Gegenstück, daher wird die aufgelöste Version danach geprüft und gepinnt, wenn sie zu neu ist. Python, Go, Rust, PHP und Ruby nutzen die Verzögerung, wenn ihre Registries Veröffentlichungsdaten liefern. Sonst steht im Pull Request, dass sie nicht angewendet wurde.

Der Pull Request enthält einen Abschnitt „Why this version“: den OSV-Fix, die gewählte Version, ihr Veröffentlichungsdatum, die Verzögerung, Ausnahmen und übersprungene neuere Releases. Ein Major-Upgrade zeigt ein Bruchrisiko von niedrig, mittel, hoch oder unbekannt, aus öffentlichen Release Notes, Node-Engines und Peer-Abhängigkeiten. Major-Upgrades bleiben abgewählt. Auto-Merge ist aus, bis du es einschaltest. Es macht einen Squash-Merge nur bei Patch- oder Minor-Fixes, nie bei einem transitiven Override, und erst, wenn alle Checks grün sind und du noch pushen darfst.

Ökosysteme

ÖkosystemDateienAutomatischer Fix
npmpackage-lock.json, pnpm-lock.yaml, yarn.lockJa, außer Yarn Berry
Pythonpoetry.lock, uv.lock, Pipfile.lock, requirements.txt gepinnt mit ==Aufgeführt, nicht angewendet
Gogo.modAufgeführt, nicht angewendet
RustCargo.lockAufgeführt, nicht angewendet
PHPcomposer.lockAufgeführt, nicht angewendet
RubyGemfile.lockAufgeführt, nicht angewendet

Berechtigungen der GitHub App

BerechtigungVerwendet für
ContentsDateien lesen, Branch und Commit erstellen.
Pull requestsÖffnen, per Squash mergen und schließen.
MetadataLesen. Standardmäßig gewährt.
ChecksCI vor einem Merge lesen und den Scandar-Check schreiben.
Commit statusesLesen, für dieselbe Merge-Entscheidung.

Lokaler OAuth-Callback: http://localhost:3010/api/auth/callback/github. Die App lauscht auf Port 3010. npm, pnpm und yarn müssen für die Lockfiles, die sie neu erzeugen, im PATH liegen.

Grenzen

  • 10 Projekte pro Repository, 60 Workspace-Mitglieder. Der Rest entfällt.
  • Ein gekürzter Git-Baum fällt auf die package.json im Stammverzeichnis zurück.
  • Der Schweregrad kommt aus database_specific.severity, dann aus dem CVSS-v3-Wert. Ohne beides ist die Advisory Unbekannt.
  • Paketgesundheit und transitive Lizenzen decken nur npm ab.
  • Die Lockfile-Neuerzeugung bricht nach 3 Minuten ab.
  • Ein Node-Prozess: SQLite und der Event-Bus im Speicher werden nicht zwischen Instanzen geteilt.

Rund um den Scan

Eine ignorierte Advisory braucht einen Grund, eine Notiz und eine Dauer. Sie verschwindet bis zum Ablauf aus Summen, Fixes, Benachrichtigungen und Pull-Request-Checks. Der Verlauf hält offene Schwachstellen 90 Tage. Exporte sind CycloneDX 1.5, SPDX 2.3, CSV und ein druckbarer Bericht. Ein Push auf den Standard-Branch kann über den Webhook der GitHub App neu scannen, und Slack oder Discord können Warnungen ab dem gewählten Schweregrad erhalten.

CI, CLI und Editoren

Derselbe Check läuft aus GitHub Actions, dem Terminal oder einem Editor-Agenten. Jeder Client ruft POST /api/v1/check mit einem API-Schlüssel auf. Der Plan braucht die Funktion api. Nichts davon ist bisher auf npm oder dem GitHub Marketplace.

Öffentliche Paket- und Advisory-Seiten

/package/<name> (auch @scope/name) und /cve/<id> (eine CVE- oder GHSA-ID) sind öffentlich. Der Name wird vor jeder Anfrage geprüft. Ein unpassender Name oder ein Paket oder eine Advisory, die OSV und die npm-Registry nicht kennen, ergibt eine 404.

Die Seite zeigt Schweregrad, betroffene und behobene Versionen sowie KEV oder EPSS nur aus bereits hier gespeicherten Daten. Einfache Erklärungen erscheinen nur, wenn sie bereits im Erklärungs-Cache liegen. Diese Seiten rufen das Modell nicht auf. Die OSV-Advisory bleibt verlinkt, weil eine gecachte Erklärung falsch sein kann.

Repository-Berichte unter /scan/… und die druckbare Seite /report sind noindex. /dashboard, /admin und /api sind in robots.txt gesperrt.