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
- Melde dich mit der GitHub App an. Sichtbar sind nur die bei der Installation gewählten Repositories.
- Projekte finden: eine
package.jsonnebenpackage-lock.json,pnpm-lock.yamloderyarn.lock. Verschachtelte Manifeste ohne eigene Lockfile zählen als Workspace-Mitglieder. - Lockfile lesen und OSV.dev abfragen. Doppelte Advisory-IDs werden zusammengeführt.
- Fix-Plan erstellen. Direkte Abhängigkeiten wechseln zu
^fixed. Transitive werden mit Overrides,pnpm.overridesoderpnpm-workspace.yamloder Yarn-resolutionsgepinnt. - 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
| Ökosystem | Dateien | Automatischer Fix |
|---|---|---|
| npm | package-lock.json, pnpm-lock.yaml, yarn.lock | Ja, außer Yarn Berry |
| Python | poetry.lock, uv.lock, Pipfile.lock, requirements.txt gepinnt mit == | Aufgeführt, nicht angewendet |
| Go | go.mod | Aufgeführt, nicht angewendet |
| Rust | Cargo.lock | Aufgeführt, nicht angewendet |
| PHP | composer.lock | Aufgeführt, nicht angewendet |
| Ruby | Gemfile.lock | Aufgeführt, nicht angewendet |
Berechtigungen der GitHub App
| Berechtigung | Verwendet für |
|---|---|
| Contents | Dateien lesen, Branch und Commit erstellen. |
| Pull requests | Öffnen, per Squash mergen und schließen. |
| Metadata | Lesen. Standardmäßig gewährt. |
| Checks | CI vor einem Merge lesen und den Scandar-Check schreiben. |
| Commit statuses | Lesen, 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.