Zum Hauptinhalt springen

Erreichbarkeit

Eine Advisory zu einer Abhängigkeit sagt, dass eine Paketversion verwundbar ist. Sie sagt nicht, ob dein Programm den verwundbaren Code erreichen kann. Die Erreichbarkeit beantwortet das für Go anhand der Binärdateien, die du tatsächlich auslieferst, und anhand des Codes deines Repositorys für JavaScript und TypeScript (npm) sowie auf Importebene für Python (PyPI) und Java und Kotlin (Maven). Sie zeigt dir, warum. Für Go analysiert sie außerdem den eigenen Code deines Repositorys (Quellmodus); siehe unten.

Was geprüft wird

Go: die Binärdateien, die du auslieferst

Wenn fremforge die Container-Images in der Registry deiner Organisation erneut scannt, wird jede Go-Binärdatei mit einem Schwachstellenbefund von govulncheck im Binärmodus gelesen. govulncheck liest die Modulliste und die Symboltabelle der Binärdatei und vergleicht sie mit der Go-Schwachstellendatenbank, die für jede Advisory die genau betroffenen Funktionen nennt.

  • Nichts in deinem Image wird gebaut oder ausgeführt. Die Binärdatei wird als Datei gelesen.
  • Es wird kein Dienst aufgerufen. Die Schwachstellendatenbank ist die eigene Kopie von fremforge der OSV-Datensätze für Go, täglich aktualisiert.
  • govulncheck (BSD-3-Clause) ist auf ein Release gepinnt und wird über Renovate aktualisiert.

Terraform- und OpenTofu-Provider: die Binärdateien, die deine Lockfiles pinnen

Ein Befund zu einem Terraform- oder OpenTofu-Provider ist ein Go-Modul, das in die Provider-Binärdatei eingebaut ist, die deine .terraform.lock.hcl pinnt. fremforge liest diese Binärdatei mit govulncheck im Binärmodus, wie eine Go-Binärdatei in einem Image, und der Befund erhält das Urteil: erreichbar, wenn eine betroffene Funktion in den Provider gelinkt ist, nicht erreichbar, wenn das Modul (oder sein Paket) in der Binärdatei ist, aber keine der Funktionen, die die Advisory nennt.

  • Provider-Releases werden ohne Symboltabelle gebaut (-ldflags=-s). Die Funktionstabelle, die Go zur Laufzeit behält, ist trotzdem da; fremforge stellt das eine Symbol wieder her, das govulncheck zum Lesen braucht, und das Ergebnis ist dasselbe wie für denselben Provider, mit seinen Symbolen gebaut. Lässt sich dieses Symbol nicht finden, bleibt das Urteil unknown (no_symbol_table).
  • Jede Provider-Version wird einmal analysiert, für jede Organisation, die sie pinnt, aus der Kopie, die der Provider-Mirror von fremforge vorhält. Nichts über dein Repository wird verwendet.
  • Eine Provider-Binärdatei über 512 MiB (zum Beispiel hashicorp/aws) behält das Urteil unknown (engine_failed).

Go: der Code deines Repositorys

Findet ein Abhängigkeits-Scan verwundbare Go-Module, führt fremforge govulncheck zusätzlich im Quellmodus auf dem gescannten Commit aus. Es prüft die Typen deiner Module und baut einen Aufrufgraphen ab deinen main-Paketen, sodass es den Aufrufpfad von einer Zeile in deinem Repository bis zur betroffenen Funktion zeigen kann, auch wenn aus diesem Commit kein Image gebaut wurde.

Dazu braucht es den Befehl go, den ein Repository zu steuern versuchen kann. fremforge führt ihn so aus, dass nichts aus deinem Repository ausgeführt und nichts anders als über den Dependency-Proxy deiner Organisation abgerufen wird. Das Design wurde vor dem Ausliefern geprüft.

  • Nichts in deinem Repository läuft. Kein go generate, keine Tests, kein Build, kein cgo (CGO_ENABLED=0), kein -toolexec. Nur der Typprüfer der Go-Toolchain selbst liest deinen Code.
  • Keine andere Toolchain. Eine toolchain-Zeile wird ignoriert (GOTOOLCHAIN=local). Eine go-Zeile, die neuer ist als das Go von fremforge, macht das Modul unknown (build_failed). fremforge hält sein Go über Renovate aktuell.
  • Keine Versionsverwaltung und kein anderes Netz. Module kommen nur aus dem Dependency-Proxy deiner Organisation, über ein Relay, das die Scan-Zugangsdaten von fremforge hinzufügt, sodass deine Paketrichtlinie gilt. Es gibt keinen Rückgriff auf einen Versionsverwaltungs-Host. Hat deine Organisation ihren Dependency-Proxy ausgeschaltet, liest der Scan Module stattdessen aus dem eigenen Scan-Cache von fremforge auf demselben Proxy. Dieser Cache hält nur öffentliche Module von proxy.golang.org, jedes gegen sum.golang.org geprüft, und verwendet keine Zugangsdaten von dir, deshalb gilt deine Paketrichtlinie für diese Lesezugriffe nicht. Eine Organisation, deren Proxy ein Modul aufgrund ihrer Richtlinie ablehnt, erhält dafür unknown; der Scan geht nie an deinem Proxy vorbei.
  • Private Module werden nie angefragt. Ein Modul unter frem.sh oder eines, das zu einem GOPRIVATE-, GONOPROXY- oder GONOSUMDB-Muster passt, das dein Repository angibt (in seinen CI-Workflows, go.env, .envrc, .env oder Makefile), wird abgelehnt, bevor eine Anfrage den Scan verlässt. Sein Pfad wird nie an den Dependency-Proxy, an proxy.golang.org oder an sum.golang.org geschickt, und alles, was es braucht, ist unknown (build_failed). Dieselbe Regel gilt für die Abfragen zu Lizenz, Release-Alter und Abhängigkeitsgraph bei Go. Siehe was bei öffentlichen Modulen Google erreicht.
  • Deine Einstellungsdateien werden nicht gelesen. Eine eingecheckte GOFLAGS-Datei, go.env oder .config/go/env, ein vendor/-Verzeichnis und eine .netrc werden ignoriert. Symlinks wird nicht gefolgt.
  • Vor der Analyse abgelehnt, als unknown (build_failed): ein Modul, das von einer go.work gesteuert wird (sie ändert, welcher Code gebaut wird), ein replace auf einen absoluten Pfad oder außerhalb des Repositorys und ein Modulpfad, der direkt ein Versionsverwaltungs-Repository nennt (….git).
  • Getrennt von den Zugangsdaten von fremforge. Die Analyse läuft in einem eigenen Container, der keine Zugangsdaten hält und nichts außer dem Relay erreicht. Sie hat eigene Speicher- und CPU-Limits.
  • Limits: 20 Module, 20.000 Dateien und 128 MiB deines Repositorys pro Scan, 512 MiB an Modul-Downloads und ein Zeitbudget von 3 Minuten pro Scan. Über einem Limit ist es unknown.
  • Tests (_test.go) werden nicht analysiert, wie im Binärmodus. Die Standardbibliothek wird nur im Binärmodus beurteilt: Der Quellmodus würde sie in der Go-Version von fremforge lesen, nicht in deiner.
  • Er lässt den Scan nie fehlschlagen und ändert nie den Status fremforge/dep-scan.

JavaScript und TypeScript: der Code deines Repositorys

Findet ein Abhängigkeits-Scan verwundbare npm-Pakete, führt fremforge Jelly auf dem gescannten Commit aus, einen statischen Aufrufgraph-Analysator für JavaScript und TypeScript der Universität Aarhus. Er prüft, ob dein Code das verwundbare Paket lädt, direkt oder über andere Pakete.

  • Jelly liest deinen Code. Es führt ihn nie aus: Nichts wird installiert, kein Paketcode läuft und kein Install-Skript läuft.

  • Die Pakete auf dem Weg zu einem verwundbaren werden nach Name und Version abgerufen und als Daten entpackt. Jedes wird gegen den Integritäts-Hash in deiner Lockfile geprüft, und die .npmrc deines Repositorys wird nicht verwendet. Sie kommen über den Dependency-Proxy deiner Organisation (siehe Woher Paketdateien kommen).

  • Jeder Tarball wird als Stream gelesen. Er wird beim Eintreffen gegen seinen Integritäts-Hash geprüft, und nur die Dateien, die Jelly liest, werden geschrieben: .js, .mjs, .cjs, .jsx, .ts, .mts, .cts, .tsx und .json. Native Binärdateien und andere große Dateien werden übersprungen, ohne aufbewahrt zu werden, sodass ein Paket wie onnxruntime-node (108 MiB) wie jedes andere analysiert wird. Dateien werden nur behalten, wenn der Hash passt.

  • Limits: ein Tarball von bis zu 512 MiB, 2 GiB entpackt, 100.000 Einträge, 10.000 geschriebene Dateien und 16 MiB pro geschriebener Datei. Alle für eine Lockfile ausgelegten Pakete zusammen können bis zu 96 MiB an geschriebenen Dateien belegen. Ein Paket über einem Limit macht die Befunde, die es brauchen, unknown (build_failed). Eine wegen ihrer Größe übersprungene Datei lässt einen Befund nie unreachable werden.

  • Unterstützte Lockfiles:

    LockfileVersionenIntegrität geprüft gegen
    package-lock.json, npm-shrinkwrap.jsonLockfile-Version 2 oder 3 (npm 7 und neuer)die Lockfile
    pnpm-lock.yaml5.x, 6 und 9die Lockfile
    yarn.lock, classicyarn 1die Lockfile (integrity oder der SHA-1 in einer älteren resolved-URL)
    yarn.lock, berryyarn 2 und neuer (__metadata-Version 4 und neuer)die Integrität, die deine Registry für diese Version veröffentlicht, weil die checksum von berry das eigene Cache-Archiv von yarn abdeckt und nicht den npm-Tarball. Ein Paket, dessen veröffentlichte Integrität sich nicht lesen lässt, wird nicht abgerufen.
    bun.lockTextformat (bun 1.2 und neuer)die Lockfile

    Für yarn classic, das keine Workspaces festhält, werden auch die package.json neben der Lockfile und ihre workspaces gelesen. bun.lockb, das ältere Binärformat von bun, wird nicht gelesen: Es ist ein undokumentiertes Speicherabbild, das sich zwischen bun-Versionen geändert hat. Seine Befunde sind unknown, und die Belege sagen, warum. Andere Lockfiles ergeben unknown.

  • Jelly (BSD-3-Clause) läuft im Scan-Job von fremforge und ruft keinen Dienst auf. Es ist auf ein Release gepinnt und wird über Renovate aktualisiert.

  • Die Analyse hat ein Zeitbudget von 2 Minuten pro Scan. Sie lässt den Scan nie fehlschlagen. Sie ändert den Status fremforge/dep-scan nur, wenn deine Organisation sich dafür entscheidet, bei nicht erreichbaren Befunden nicht zu blockieren.

Python, Java und Kotlin: die Importe deines Repositorys

Findet ein Abhängigkeits-Scan verwundbare PyPI- oder Maven-Pakete, prüft fremforge, ob dein Code sie importiert. Das ist nur Importebene: Es sagt dir, dass ein Paket geladen wird, nie, dass der verwundbare Code läuft, und es ergibt nie unreachable.

  • Python. Deine .py-Dateien werden mit dem eigenen ast-Modul von Python geparst, das nur parst. Nichts wird importiert oder ausgeführt. fremforge liest import- und from … import-Anweisungen sowie Aufrufe von importlib.import_module(...) und __import__(...) mit einem literalen Namen. Eine Datei, die sich mit aktuellem Python nicht parsen lässt, etwa Python-2-Code, wird stattdessen Zeile für Zeile nach ihren Import-Anweisungen gelesen. Relative Importe (from . import x) sind deine eigenen Module und werden übersprungen, ebenso virtuelle Umgebungen (.venv, venv, site-packages) und Symlinks.

  • Python, über andere Pakete. Importiert dein Code ein verwundbares Paket nicht selbst, folgt fremforge den Paketen, die dein Code importiert: Es liest deren Code auf dieselbe Weise aus ihren Wheels, beginnend bei den Modulen, die dein Code importiert, und folgt nur deren eigenen Importen. Importiert so erreichter Code das verwundbare Paket, ist der Befund Importiert, und seine Belege zeigen den Pfad: dein Import, dann der Import in jedem Paket, zum Beispiel idna über requests. Einem Modul, das nichts lädt (etwa die help.py eines Pakets), und Importen unter if TYPE_CHECKING: wird nicht gefolgt. Dieser Weg geht höchstens drei Pakete tief und liest pro Scan höchstens 40 Wheels von je bis zu 16 MiB. Er fügt nur Urteile Importiert hinzu; ein Pfad, dem er nicht folgen kann, lässt den Befund unknown.

  • Java, Kotlin, Groovy und Scala. fremforge liest import-Anweisungen, voll qualifizierte Klassennamen im Code sowie Class.forName("…") und loadClass("…") mit einem literalen Namen. Kommentare und String-Literale werden ignoriert, ebenso build/ und target/. Nichts wird kompiliert.

  • Java und Kotlin, über andere Pakete. Importiert dein Code ein verwundbares Maven-Paket nicht selbst, folgt fremforge den Paketen, die dein Code importiert, in ihren kompilierten Klassen. Es beginnt bei den Klassen, die dein Code importiert (bei einem Wildcard-import a.b.* jede Klasse des Pakets). Von dort folgt es den Klassen, die sie verwenden: jeder Klasse, deren Methode aufgerufen, die erzeugt, auf die gecastet oder deren Feld gelesen wird, und jeder Oberklasse und jedem Interface. Diese werden aus dem Konstantenpool jeder Klassendatei gelesen. Verwendet eine so erreichte Klasse eine Klasse des verwundbaren Pakets, ist der Befund Importiert. Seine Belege zeigen den Pfad: dein Import, dann die Quelldatei und Zeile in jedem Paket, in der das nächste verwendet wird. Ein Beispiel ist commons-text über commons-configuration2. Einer Klasse, die nichts erreicht, wird nicht gefolgt, ebenso wenig einer Klasse, die über einen String per Name geladen wird. Klassendateien werden als Daten gelesen: Keine Klasse wird geladen oder ausgeführt, und keine JVM ist beteiligt. Dieser Weg geht höchstens drei Pakete tief und liest pro Scan höchstens 40 JARs von je bis zu 32 MiB, eins nach dem anderen. Er fügt nur Urteile Importiert hinzu; ein Pfad, dem er nicht folgen kann, lässt den Befund unknown.

  • Welche Namen ein Paket bereitstellt, ergibt sich aus der Dateiliste seines veröffentlichten Archivs, als Daten gelesen:

    • PyPI: das Wheel für diese Version. Ein Namespace-Paket wird zu seinem ersten echten Paket aufgelöst, zum Beispiel google.protobuf für protobuf.
    • PyPI, ein Release ohne Wheel (nur sdist): das Quellarchiv, als Daten gelesen und nie installiert. setup.py wird weder ausgeführt noch gelesen. Die Namen kommen aus den Paketlisten in setup.cfg oder pyproject.toml (setuptools, hatch, flit und poetry) oder andernfalls aus den Verzeichnissen mit einer __init__.py, auf oberster Ebene, unter src/ oder unter einem Verzeichnis wie lib/. So stellt pysaml2 saml2 bereit und pycrypto Crypto. PKG-INFO muss dasselbe Projekt nennen. Archive bis 16 MiB werden gelesen (.tar.gz, .tar, .zip). Ein Release, das in keinem Index steht, oder ein sdist, das nichts nennt (zum Beispiel ein .tar.bz2), fällt auf den Projektnamen zurück, sodass requests für import requests steht; das mapping der Belege sagt das.
    • Maven: das JAR auf Maven Central und die Java-Pakete, in denen seine Klassen liegen.

    Bei einem Wheel oder JAR wird nur das Verzeichnis des Archivs abgerufen, mit HTTP-Range-Requests, sodass ein großes nur ein paar Kilobyte kostet. Der Weg über andere Pakete liest das ganze Wheel oder JAR jedes Pakets, dem er folgt, und ein sdist wird immer ganz gelesen. Nichts wird installiert, gebaut oder ausgeführt.

  • Dein Repository wird nicht gebaut. Erreichbarkeit für Java mit Aufrufgraphen, wie die experimentelle JAR-Analyse von osv-scanner oder jdeps, braucht ein gebautes JAR. Ein Pull-Request-Scan baut dein Projekt nicht, deshalb werden diese Werkzeuge nicht verwendet.

  • Die Analyse hat ein Zeitbudget von 1 Minute pro Ökosystem und Scan und läuft parallel zur npm-Analyse. Sie lässt den Scan nie fehlschlagen und ändert nie den Status fremforge/dep-scan.

Woher Paketdateien kommen

npm-Tarballs, PyPI-Indizes und -Wheels sowie Maven-JARs werden über den Dependency-Proxy deiner Organisation gelesen, auf einer internen Route, die nur der Scan-Dienst von fremforge erreicht. So gelten für sie die Paketrichtlinie, der Cache, die Speichergrenze und die Upstream-Rate deiner Organisation wie für jeden anderen Abruf, und was der Scan abruft, ist für deine Builds im Cache.

  • Lehnt deine Richtlinie ein Paket ab (zum Beispiel Malware, ein zu neues Release oder eine Lizenzregel), ruft der Scan es nirgendwo anders ab. Die Befunde, die es brauchen, sind unknown (build_failed), und die Belege nennen die Entscheidung des Proxys.
  • Hat deine Organisation den Dependency-Proxy ausgeschaltet oder kann der Proxy nicht antworten, werden die Dateien stattdessen aus den öffentlichen Registries gelesen (npmjs, PyPI, Maven Central), wie bisher.
  • Dateien, die der Scan abruft, zählen wie jede andere Datei im Cache zum Proxy-Speicher deiner Organisation.

Die Ebenen

Ein Urteil hat eine Ebene: wie viel die Engine sehen konnte.

EbeneBedeutung
functionDie Advisory nennt die betroffenen Funktionen, und die Engine hat nach einem Pfad zu ihnen gesucht. Das liefert govulncheck für Go.
importDie Advisory nennt keine betroffenen Funktionen. Die Engine kann nur sagen, ob das verwundbare Paket geladen wird.

npm-Advisories nennen fast nie betroffene Funktionen. Bei einer Messung am 2026-10-12 tat das keiner der 230.287 npm-Datensätze in der OSV-Datenbank. Urteile für JavaScript und TypeScript sind deshalb Importebene: Sie sagen dir, dass dein Code das verwundbare Paket lädt, nicht, dass er den verwundbaren Code aufruft. Nennt eine npm-Advisory doch betroffene Funktionen, prüft Jelly sie auf Funktionsebene.

Urteile für Python und Maven sind immer Importebene. Dieselbe Messung fand Daten zu betroffenen Funktionen in 2 von 26.221 PyPI-Datensätzen und in keinem der 7.190 Maven-Datensätze.

Die drei Urteile

Jeder Abhängigkeits- und Image-Befund trägt eines davon:

UrteilGo (govulncheck)JavaScript und TypeScript (Jelly)Python, Java und Kotlin (Importebene)
ErreichbarEine betroffene Funktion ist in die Binärdatei gelinkt. Der Go-Linker verwirft Code, den nichts aufrufen kann, eine gelinkte Funktion ist also eine, die dein Programm erreichen kann. Die Markierung nennt die Funktion, zum Beispiel html.Renderer.renderLink. Im Quellmodus: Ein Aufrufpfad aus deinem Code erreicht eine betroffene Funktion; die Markierung gibt Datei und Zeile des letzten Aufrufs in deinem Repository an, bevor der Pfad in die Abhängigkeit eintritt, zum Beispiel deinen Handler statt main. Der ganze Pfad steht in den Belegen.Auf Importebene, angezeigt als Importiert: Dein Code lädt das Paket in der verwundbaren Version, direkt oder über andere Pakete. Auf Funktionsebene, angezeigt als Erreichbar: Ein Aufruf in deinem Code kann eine betroffene Funktion erreichen. Die Markierung gibt Datei und Zeile in deinem Repository an, zum Beispiel src/session.ts:12.Angezeigt als Importiert: Dein Code importiert ein Modul oder Java-Paket, das das verwundbare Paket bereitstellt. Die Markierung gibt Datei und Zeile des Imports an, zum Beispiel app/main.py:2.
Nicht erreichbar (unreachable)Das Modul ist in einer betroffenen Version in der Binärdatei, die Advisory nennt die betroffenen Funktionen, govulncheck ist vollständig durchgelaufen, und keine dieser Funktionen ist in der Binärdatei. Im Quellmodus: Das Modul wird in einer betroffenen Version verwendet, govulncheck hat keinen Aufrufpfad zu einer betroffenen Funktion gefunden, und nichts, dem govulncheck nicht folgen kann (Reflection, Dateien für andere Plattformen, cgo, Plugins), steht in deinem Code.Die Advisory nennt die betroffenen Funktionen, Jelly ist vollständig durchgelaufen, wobei jedes Paket auf dem Weg verfügbar war, und kein Aufruf in deinem Code erreicht eine davon. Ohne diese Funktionsdaten ist ein Paket, das dein Code nie lädt, unknown, nicht unreachable.Nie. Importen in anderen Paketen wird nur so weit gefolgt, wie sie ein Modul oder eine Klasse literal nennen, ein Paket, das dein Code scheinbar nicht lädt, kann also trotzdem geladen werden.
UnbekanntAlles andere. Das ist der Standard, und es wird nie als sicher behandelt.Ebenso.Ebenso, einschließlich jedes Pakets, das dein Code nicht importiert.

unreachable verlangt alle seine Bedingungen. Eine fehlende Eingabe ergibt immer unknown, mit dem Grund:

GrundWarum
no_symbol_dataDie Advisory nennt die betroffenen Funktionen nicht, das Fehlen eines Pfads beweist also nichts. Für npm ist das der übliche Grund, wenn dein Code das Paket nicht lädt. Für Python und Maven ist es der Grund, wann immer dein Code das Paket nicht importiert.
no_symbol_tableGo: Die Binärdatei wurde mit -ldflags=-s gebaut. Ihre Symbole lassen sich nicht lesen, deshalb ist keines der beiden Urteile verdient. Baue ohne -s (-w zu behalten ist in Ordnung), um Urteile zu bekommen. Terraform-Provider: Das Symbol, das fremforge wiederherstellt, wurde in dieser Binärdatei nicht gefunden.
build_failedGo-Quellmodus: Das Modul wurde vor der Analyse abgelehnt (siehe oben), konnte nicht geladen werden, oder ein Modul konnte nicht aus deinem Dependency-Proxy abgerufen werden. npm: Die Lockfile ist keines der unterstützten Formate, oder ein Paket auf dem Weg konnte nicht abgerufen werden, lag über einem Limit oder passte nicht zu seinem Integritäts-Hash. Python und Maven: Das Wheel, das sdist oder das JAR konnte nicht gelesen werden, zum Beispiel ein Artefakt nur mit POM oder eines, das nicht auf Maven Central liegt.
dynamic_codeDein Code lädt Module oder Klassen über berechnete Namen, ein fehlender Aufrufpfad oder Import beweist also nichts. npm: require(name) und import(name). Python: importlib.import_module(name) und __import__(name). Java: Class.forName(name) und loadClass(name). Go-Quellmodus: das Paket plugin oder //go:linkname.
reflectionGo-Quellmodus: Dein Code ruft Methoden über reflect auf (MethodByName, Method, Call) oder verwendet text/template oder html/template, wenn die Advisory Methoden nennt. govulncheck kann diesen Aufrufen nicht folgen, ein fehlender Aufrufpfad beweist also nichts.
build_constraintsGo-Quellmodus: Eine Datei, die die Analyse nicht geladen hat, importiert andere Pakete. Die Analyse lädt deinen Code wie für Linux auf amd64 ohne cgo, eine _windows.go-Datei, eine Datei, deren //go:build-Zeile Linux ausschließt, oder eine cgo-Datei ist also nicht im Aufrufgraphen, und ein nur dort gemachter Aufruf würde übersehen. Ein Paket, das nur mit cgo baut (zum Beispiel eine Desktop-Oberfläche auf einem reinen cgo-Toolkit), wird aus der Analyse herausgelassen, statt sie scheitern zu lassen: Der Rest des Moduls wird analysiert, und jedes Modul, das dieses Paket importiert, bekommt diesen Grund statt unreachable.
timeoutDie Analyse hat ihr Zeitbudget überschritten (5 Minuten pro Image für Go, 2 Minuten pro Scan für npm, 1 Minute pro Ökosystem und Scan für Python und Maven).
engine_no_matchGo: govulncheck hat diese Modulversion nicht als von der Advisory betroffen gemeldet, der Image-Scanner aber schon. Keinem der beiden wird mehr vertraut als dem anderen.
oom_killedGo-Quellmodus: Die Analyse hatte nicht genug Speicher und wurde gestoppt, es wurde also nichts entschieden.
engine_failedDie Analyse konnte für diese Binärdatei oder dieses Repository nicht laufen.
not_analysedEs wurde kein Urteil berechnet: Der Befund wurde seit Einführung der Erreichbarkeit nicht gescannt, oder für einen Go-Befund gibt es kein aus seinem Commit gebautes Image.
unsupported_ecosystemEin Abhängigkeitsbefund außerhalb von Go, npm, PyPI, Maven und Terraform-Providern, zum Beispiel NuGet oder Cargo.

Abhängigkeitsbefunde

Go. Ein Go-Abhängigkeitsbefund erhält sein Urteil im Binärmodus, aus einem Image, das aus genau diesem Commit gebaut wurde. Wo der Quellmodus an ist (bisher in den internen Organisationen von fremforge), erhält er außerdem bei jedem Scan eines, mit dem Aufrufpfad in deinem Repository. Versieh deine Images mit den beiden Standard-OCI-Labels:

org.opencontainers.image.source=https://frem.sh/<org>/<repo>
org.opencontainers.image.revision=<full commit sha>

docker/metadata-action setzt beide. Das Urteil gilt nur für den Commit, den das Image nennt, und für die Modulversionen, mit denen die Binärdateien gebaut wurden. Konnte eine Go-Binärdatei in diesem Image nicht gelesen werden, bleibt der Abhängigkeitsbefund unknown. Tragen mehrere Binärdateien das Modul, ist der Befund erreichbar, wenn eine von ihnen ihn erreicht.

Beurteilen beide Modi denselben Befund im selben Commit, löscht keiner den anderen aus: Ein unknown aus dem einen ersetzt nie ein Urteil aus dem anderen, und nicht erreichbar aus dem einen ersetzt nie erreichbar aus dem anderen. Belege aus dem Quellmodus tragen "mode": "source".

npm, PyPI und Maven. Urteile kommen mit dem Abhängigkeits-Scan selbst: bei jedem Pull-Request-Scan und beim Scan deines Standard-Branches nach jedem Push (höchstens einmal pro Stunde). Ein Urteil gehört immer zu dem Commit, der gescannt wurde. Erscheinen dasselbe Paket und dieselbe Advisory in mehreren Lockfiles, ist der Befund erreichbar, wenn eine von ihnen ihn erreicht.

Wie fremforge sie nutzt

Sortierung. Die Befundlisten Abhängigkeiten und Container-Images sind erreichbar zuerst sortiert, dann unbekannt, dann nicht erreichbar. Innerhalb jeder Gruppe sind sie nach Schweregrad sortiert, dann bekannt ausgenutzt vor dem Rest, dann nach EPSS. Ein Befund ist bekannt ausgenutzt, wenn eine seiner CVE-IDs, seine eigenen oder die Aliasse seiner Advisory, in der EU-Schwachstellendatenbank der ENISA oder im Katalog Known Exploited Vulnerabilities der CISA als ausgenutzt gelistet ist. Beide Listen zeigen ein Badge Bekannt ausgenutzt, dessen Tooltip die Quelle nennt: EU (ENISA EUVD), US (CISA KEV) oder beide, und über jeder Liste zeigt Nur bekannt ausgenutzte nur diese Befunde (in der Befund-API ?known_exploited=true). Beide Listen werden täglich aktualisiert. Ein Befund Importiert wird mit den erreichbaren sortiert. Dieselbe Reihenfolge verwenden:

  • der Tab Empfehlungen, auf dem eine Karte (ein Upgrade eines Pakets in einem Repository) das am stärksten erreichbare Urteil der Befunde übernimmt, die sie behebt, und als Erreichbar oder No call path gekennzeichnet ist;
  • Top fixable today im wöchentlichen Digest, das das Urteil jeder Zeile zeigt;
  • die Befund-API mit ?sort=risk.

Warnungen. Wird ein offener Abhängigkeitsbefund erreichbar oder bekannt ausgenutzt, erhält dein SIEM sofort ein Audit-Ereignis, und die Sicherheitskontakte der Organisation erhalten eine E-Mail, einmal pro Befund: siehe Warnungen zu Befunden. Bekannt ausgenutzte und erreichbare mit Schweregrad HIGH oder CRITICAL werden sofort gemailt. Erreichbare mit Schweregrad MEDIUM oder LOW kommen in die tägliche Zusammenfassung jeder Person, oder sofort bei jemandem, der die Zusammenfassung ausgeschaltet hat. Die Einrichtungs-Checkliste unter Sicherheit › Übersicht zeigt, welche deiner Images Go-Binärdateien ohne Symbole enthalten.

Die Gruppe wahrscheinlich nicht ausnutzbar. Befunde, die nicht erreichbar sind, wandern in eine zugeklappte Gruppe am Ende der Liste, betitelt mit ihrer Anzahl. Sie bleiben sichtbar, auswählbar und verwerfbar, und sie werden in jeder Summe mitgezählt.

Nichts wird versteckt oder verworfen. Ein Urteil schreibt nie ein Verwerfen. Es ändert die SLA eines Befunds nur, wenn deine Organisation sich für den SLA-Faktor entscheidet. Standardmäßig liest der Commit-Status (fremforge/dep-scan, fremforge/image-scan) keine Urteile: Was einen Merge oder einen Pull blockiert, bleibt unverändert. Die einzige Ausnahme ist die optionale Richtlinie, Pull Requests bei nicht erreichbaren Befunden nicht zu blockieren, die nur für fremforge/dep-scan gilt.

SLA-Faktor (optional)

Ein Owner der Organisation kann die SLA nach Schweregrad von Befunden strecken, die nicht erreichbar sind, unter Sicherheit › Priorisieren › Behebungsfrist (SLA) (/<org>/_admin/security/prioritise/sla) oder mit unreachable_sla_multiplier über PUT /orgs/{org}/security/sla-policy. Der Wert ist eine ganze Zahl von 1 bis 4. Der Standard, 1, bedeutet aus.

  • Nur unreachable-Befunde werden gestreckt. Erreichbare und unbekannte Befunde behalten immer die volle SLA, ebenso ein Befund, der nicht analysiert wurde.
  • Ein bekannt ausgenutzter Befund (gelistet von EU (ENISA EUVD) oder US (CISA KEV), siehe Sortierung oben) wird nie gestreckt, bei keinem Schweregrad und unabhängig von seinem Urteil.
  • Ein kritischer Befund, dessen EPSS-Score in den obersten 10 % liegt (Perzentil 0,90 oder mehr), wird nie gestreckt, unabhängig von seinem Urteil.
  • Die Frist wird immer ab dem ersten Auftreten des Befunds gerechnet. Findet ein späterer Scan einen Aufrufpfad oder kann er es nicht entscheiden, gilt sofort wieder die volle SLA, sodass der Befund direkt über der SLA liegen kann. Die SLA-Pille sagt dann, warum.
  • Ist der Faktor an, zeigt eine gestreckte SLA-Pille ein kleines ×2 (oder ×3, ×4) und einen Tooltip mit beiden Fristen. Die Zahl der überschrittenen SLAs im wöchentlichen Digest, die Kachel in der Übersicht und das SIEM-Ereignis code-security.sla.breached verwenden dieselben gestreckten Fristen.
  • Der Faktor ändert nur Fristen. Er ändert nicht, was einen Pull Request blockiert, und er versteckt nichts.

Jede Änderung wird als code-security.sla_policy.updated auditiert, mit dem vorherigen Wert.

Bei nicht erreichbaren Befunden nicht blockieren (optional)

Standardmäßig blockiert jeder Abhängigkeitsbefund auf oder über deinem Blockierschwellenwert den Pull Request, unabhängig von seinem Urteil. Ein Owner der Organisation kann festlegen, dass ein Befund mit nicht erreichbar fremforge/dep-scan nicht blockiert. Das ist aus, solange du es nicht einschaltest.

Das Risiko. Ein fehlender Aufrufpfad ist ein starker Beleg, kein Beweis (siehe Was statische Analyse nicht sieht). Übersieht die Analyse einen Pfad über Reflection, ein Plugin, einen dynamischen Import, Dependency Injection oder Code außerhalb des Repositorys, oder nennt die Advisory die falschen Funktionen, lässt ein falsches nicht erreichbar eine echte, erreichbare Schwachstelle durch den Merge. Schalte das nur dort ein, wo du das in Kauf nimmst, und erwäge, es auf die Repositorys zu beschränken, in denen du der Analyse vertraust.

Schalte es unter Sicherheit › Priorisieren › Pull-Request-Prüfungen (/<org>/_admin/security/prioritise/pr-checks) ein oder mit PUT /orgs/{org}/security/dep-scan-unreachable-policy (siehe API). Du kannst es auf eine Liste von Repositorys beschränken; eine leere Liste bedeutet jedes Repository der Organisation.

Was es ändert und was es nie ändert:

  • Nur unreachable mit Belegen qualifiziert sich. Das Urteil des Befunds für den Head-Commit des Pull Requests muss nicht erreichbar sein, berechnet von einer Engine mit ihrer Version und den betroffenen Funktionen der Advisory, die sie geprüft hat. Heute heißt das Go sowie JavaScript und TypeScript. Für Go liefert govulncheck das Urteil im Binärmodus, sobald ein aus dem Head-Commit des Pull Requests gebautes Image gescannt wurde; ein Urteil, das nach dem Scan eintrifft, gilt ab dem nächsten Scan des Pull Requests. Wo der Quellmodus an ist (bisher in den internen Organisationen von fremforge), liefert er auch beim Pull-Request-Scan selbst eines. Für JavaScript und TypeScript liefert Jelly es, wenn die Advisory betroffene Funktionen nennt. Urteile für Python, Java und Kotlin sind Importebene und nie unreachable, sie blockieren also immer.
  • unknown blockiert immer. Es gibt keine Option, bei unknown nicht zu blockieren, und ein Befund, der nicht analysiert wurde, ist unknown.
  • Malware und bekannt ausgenutzte Schwachstellen blockieren immer, unabhängig vom Urteil: eine MAL--Advisory oder eine als bösartig markierte Advisory und eine Schwachstelle, deren CVE-IDs von EU (ENISA EUVD) oder US (CISA KEV) als ausgenutzt gelistet sind. Kann fremforge diese Fakten während eines Scans nicht lesen, wird bei diesem Scan nichts durchgelassen.
  • Nichts wird versteckt. Der Befund wird gespeichert, gelistet, in jeder Summe mitgezählt und gemeldet wie jeder andere. Er wird nicht verworfen, und seine SLA bleibt unverändert (es sei denn, der SLA-Faktor ist ebenfalls an).
  • Nur Pull Requests. Der Scan deines Standard-Branches wird genau wie bisher festgehalten.
  • Treffer auf der Sperrliste und der Blockierschwellenwert bleiben unverändert. Ein Befund unter dem Schwellenwert hat nie blockiert, und eine gesperrte Komponente blockiert weiterhin.

Die Blockierung kehrt zurück. Findet ein späterer Scan des Pull Requests einen Aufrufpfad oder kann er es nicht entscheiden, blockiert der Befund wieder. Ein außerhalb eines Scans berechnetes Urteil (govulncheck auf einem Image) und das Ausschalten oder Einschränken der Richtlinie werden innerhalb einer Stunde übernommen: fremforge prüft jeden Pull Request erneut, der dank der Richtlinie durchgekommen ist, und berechnet seinen Status, Kommentar und sein Audit-Ereignis neu. Dasselbe geschieht, wenn ein Befund bekannt ausgenutzt wird.

Was der Pull Request zeigt. Der Status fremforge/dep-scan sagt, wie viele Befunde nicht blockiert haben, zum Beispiel 2 finding(s); 1 at or above critical with no call path, not blocking (org policy). Der Kommentar kennzeichnet jeden solchen Befund als not blocking und listet sie unter Not blocking: no call path (org policy) mit der Engine, ihrer Version, dem Datum der Schwachstellendatenbank und den Funktionen, die sie geprüft hat. Ein Befund ohne Aufrufpfad, der trotzdem blockiert, steht unter Blocking although no call path was found, mit dem Grund (Malware oder bekannt ausgenutzt).

Audit. Jede Änderung der Richtlinie wird als code-security.deps.unreachable_policy.updated auditiert, mit dem neuen und dem vorherigen Wert, ob er sich geändert hat und ob die Änderung aus der Konsole oder der API kam. Jeder Pull-Request-Scan, während die Richtlinie gilt, hält in seinem Ereignis code-security.dep_scan.ingest jeden Befund fest, der nicht blockiert hat (unreachable_not_blocking, mit der Engine, Version und dem Datenbankdatum, auf die er sich stützt), und jeden, der trotzdem blockiert hat (unreachable_blocked_anyway, mit why). Eine erneute Prüfung trägt trigger: unreachable_policy_recheck und den Grund. Beides erreicht deine SIEM-Endpunkte.

Wenn sich ein Urteil ändert: reachability_changed

Ein Verwerfen oder eine Ausnahme kann auf einem Urteil beruhen. Wenn du einen Abhängigkeits- oder Image-Befund mit dem Urteil nicht erreichbar verwirfst oder eine Ausnahme dafür beantragst, hält fremforge das Urteil fest, auf das du dich gestützt hast: die Engine, ihre Version, das Datenbankdatum und den Commit oder das Image, für das es berechnet wurde. Das Verwerfen-Panel sagt das.

Jede Stunde prüft fremforge diese Verwerfungen und Ausnahmen. Findet ein Scan nach dem Verwerfen denselben Befund reachable oder kann er es nicht entscheiden (unknown):

  • wird eine Ausnahme mit dem Grund reachability_changed widerrufen;
  • wird ein einfaches Verwerfen widerrufen: Der Befund öffnet sich wieder, und ein dadurch entstandenes repository-weites Verwerfen gilt für spätere Scans nicht mehr;
  • meldet sich der Befund erneut über dieselbe Sicherheitswarnung wie ein abgelaufenes Verwerfen;
  • sind beide Audit-Ereignisse (code-security.exception.revoked oder code-security.deps.dismissal_revoked und code-security.images.dismissal_revoked) mit dem zugrunde gelegten und dem neuen Urteil, und sie erreichen deine SIEM-Endpunkte. Das Befund-Ereignis sagt es ebenfalls: security.finding.exception_revoked oder bei einem einfachen Verwerfen security.finding.dismissal_revoked, beide mit transition_reason reachability_changed.

Ein Befund, der nicht erneut analysiert wurde, behält sein Verwerfen: Das Fehlen eines neuen Scans ist kein neues Urteil. Ein Verwerfen, das erfolgte, als das Urteil nicht unreachable war, hält nichts fest und wird von dieser Prüfung nie widerrufen, und Verwerfungen von vor Einführung dieser Prüfung werden nicht geprüft. Hast du einen Befund aus einem Grund verworfen, der nicht von der Erreichbarkeit abhängt, verwirf ihn nach dem Widerruf erneut; das Urteil ist dann nicht mehr unreachable, sodass das neue Verwerfen bestehen bleibt.

Triage-Signale für SAST

SAST-Befunde haben keinen Aufrufgraphen, deshalb sortieren sie stattdessen drei deterministische Signale. Kein KI-Modell ist beteiligt.

SignalWas es ist
OrtAus dem Dateipfad: Testcode (test/, __tests__/, *.test.ts, *_test.go, test_*.py, *Test.java und Ähnliches), Beispiele und Doku, Code von Dritten (vendor/, third_party/, node_modules/) und generierter Code (*.pb.go, *.min.js, gen/, zz_generated* und Ähnliches).
Taint-PfadDie Taint-Mode-Regeln von OpenGrep verfolgen Daten von einer Quelle, etwa Benutzereingaben, bis zur Senke. Ein Treffer mit Spur wird als Taint-Pfad gekennzeichnet und steht über einem reinen Muster-Treffer. Gespeichert wird nur die Tatsache, nie die Spur.
Hier oft verworfenPersonen haben dieselbe Regel in den letzten 90 Tagen bei mindestens 2 anderen Befunden in diesem Repository oder bei 5 in der Organisation verworfen. Bots, automatisches Auflösen und andere Systemakteure zählen nicht.

Ein Befund in Test-, Beispiel-, Drittanbieter- oder generiertem Code oder einer, der als hier oft verworfen gekennzeichnet ist, wandert in eine zugeklappte Gruppe Geringeres Vertrauen am Ende der SAST-Liste, betitelt mit ihrer Anzahl. Ein Taint-Pfad holt einen Befund nicht aus dieser Gruppe heraus: Ein Taint-Treffer in einer Testdatei ist trotzdem in einer Testdatei. Innerhalb jeder Gruppe sind Befunde nach Schweregrad sortiert, dann nach Taint-Pfad, dann nach Alter, die ältesten zuerst.

Wie die Gruppe wahrscheinlich nicht ausnutzbar werden Befunde mit geringerem Vertrauen nie versteckt oder verworfen: Sie behalten ihre volle SLA, werden überall mitgezählt und lassen sich wie jeder andere auswählen, beheben und verwerfen. Die API für SAST-Befunde gibt die Signale bei jedem Befund als triage-Objekt zurück, und ?sort=risk listet Befunde über alle Seiten in dieser Reihenfolge.

Pull-Request-Kommentar. Der Kommentar des Abhängigkeits-Scans sortiert Befunde auf dieselbe Weise und kennzeichnet jeden mit seinem Urteil, wenn es eines für den Commit des Pull Requests gibt: reachable mit der Funktion oder Datei und Zeile, imported mit Datei und Zeile (npm, Python, Java und Kotlin) oder no call path. Ist die Richtlinie, bei nicht erreichbaren Befunden nicht zu blockieren, an, listet er auch, welche Befunde nicht blockiert haben und warum.

Abdeckung messen

Der Anteil deiner offenen Abhängigkeitsbefunde mit Urteil und der Anteil, der nicht erreichbar ist, pro Ökosystem und über 30 oder 90 Tage, stehen auf der Seite Behebungskennzahlen.

Was statische Analyse nicht sieht

Ein fehlender Aufrufpfad ist ein starker Beleg, kein Beweis. Keine der Engines sieht Code, der über Reflection, Plugins, unsafe, eval, Dependency Injection oder generierten Code erreicht wird, oder Code außerhalb des Analysierten: eine separate CLI, eine gemeinsam genutzte Bibliothek oder bei Go alles außerhalb der Binärdatei. Eine Advisory kann auch die falschen Funktionen nennen.

Im Go-Quellmodus deckt der Aufrufgraph deine main-Pakete und exportierten Funktionen ab, wie sie für Linux auf amd64 ohne cgo gebaut werden. Aufrufen über Interface-Werte und Funktionswerte wird gefolgt. Aufrufen über Reflection und Aufrufen, die nur in Dateien für andere Plattformen oder in cgo-Dateien stehen, nicht, weshalb diese Befunde unknown (reflection, build_constraints) statt nicht erreichbar sind.

Für JavaScript und TypeScript ist der Aufrufgraph eine Näherung. Jelly ist ein Analysator auf Forschungsniveau, und ein dynamisches require oder import() verhindert jedes unreachable-Urteil für das Repository. Ein Urteil Importiert sagt, dass das Paket geladen wird. Es sagt nicht, dass der verwundbare Code läuft.

Für Python sowie für Java und Kotlin wird Importen über andere Pakete gefolgt (siehe oben). Bei Python funktioniert das nur so weit, wie deren Code ein Modul literal nennt. Bei Java und Kotlin funktioniert es nur so weit, wie deren kompilierte Klassen eine Klasse nennen. Einem Paket, das Module oder Klassen über berechnete Namen, ServiceLoader oder Reflection lädt, wird über diesen Punkt hinaus nicht gefolgt. Frameworks, die Klassen aus der Konfiguration laden, etwa JDBC-Treiber und Dependency Injection, werden ebenfalls nicht gesehen. Ein Java- oder Kotlin-Paket, das nur so verwendet wird, erscheint als unknown, obwohl es geladen wird.

Deshalb heißt die Gruppe wahrscheinlich nicht ausnutzbar, und deshalb zeigt jedes Urteil die Engine, ihre Version und das Datenbankdatum: Prüfe die Belege, bevor du einen Befund verwirfst.

API

Jeder Befund aus GET /orgs/{org}/code-security/deps/findings und GET /orgs/{org}/code-security/images/findings trägt ein reachability-Objekt. Für eine Go-Binärdatei:

"reachability": {
  "verdict": "reachable",
  "level": "function",
  "reason_unknown": null,
  "engine": "govulncheck",
  "engine_version": "v1.8.0",
  "db_version": "2026-10-10T11:47:18Z",
  "advisory_id": "GO-2026-5320",
  "evidence": {
    "binary": "usr/local/bin/app",
    "frames": [{ "module": "github.com/yuin/goldmark", "package": "github.com/yuin/goldmark/renderer/html", "receiver": "Renderer", "function": "renderLink" }]
  },
  "computed_at": "2026-10-12T05:40:00.000Z"
}

Im Go-Quellmodus laufen die Frames vom Einstiegspunkt deines Repositorys bis zur betroffenen Funktion, durch die Standardbibliothek und deinen eigenen Handler (ein eingeschleuster Test, 2026-10-13):

"reachability": {
  "verdict": "reachable",
  "level": "function",
  "reason_unknown": null,
  "engine": "govulncheck",
  "engine_version": "v1.8.0 (source, go1.27.2)",
  "db_version": "2026-10-10T11:47:18.507452919Z",
  "advisory_id": "GO-2026-6278",
  "evidence": {
    "mode": "source",
    "manifest": "reach-go/a/go.mod",
    "module": "github.com/gorilla/websocket",
    "version": "v1.5.0",
    "symbols": ["github.com/gorilla/websocket.*Upgrader.Upgrade"],
    "frames": [
      { "file": "reach-go/a/main.go", "line": 22, "go_package": "example.com/a", "function": "main" },
      { "file": "src/net/http/server.go", "line": 3604, "package": "stdlib@v1.27.2", "go_package": "net/http", "receiver": "*Server", "function": "Serve" },
      { "file": "src/net/http/server.go", "line": 2358, "package": "stdlib@v1.27.2", "go_package": "net/http", "receiver": "HandlerFunc", "function": "ServeHTTP" },
      { "file": "reach-go/a/main.go", "line": 13, "go_package": "example.com/a", "function": "handler" },
      { "file": "server.go", "line": 125, "package": "github.com/gorilla/websocket@v1.5.0", "go_package": "github.com/gorilla/websocket", "receiver": "*Upgrader", "function": "Upgrade" }
    ]
  },
  "computed_at": "2026-10-13T19:43:52.589Z"
}

Ein Frame ohne package liegt in deinem Repository, mit einer file relativ zum Repository. Ein Frame mit package liegt in einer Abhängigkeit oder der Standardbibliothek, und seine file ist relativ zu diesem Modul. Es werden höchstens 8 Frames behalten: der Einstiegspunkt, dann die letzten 7 bis zur betroffenen Funktion (das Beispiel oben lässt 3 Frames der Standardbibliothek weg).

Für ein npm-Paket, das dein Code über ein anderes Paket lädt:

"reachability": {
  "verdict": "reachable",
  "level": "import",
  "reason_unknown": null,
  "engine": "jelly",
  "engine_version": "0.13.0",
  "db_version": "2026-10-12T02:00:00.000Z",
  "advisory_id": "GHSA-pxg6-pf52-xh8x",
  "evidence": {
    "manifest": "package-lock.json",
    "package": "cookie",
    "version": "0.6.0",
    "frames": [
      { "file": "src/server.ts", "line": 3 },
      { "file": "index.js", "line": 9, "package": "express@4.21.0" },
      { "file": "index.js", "line": 1, "package": "cookie@0.6.0" }
    ]
  },
  "computed_at": "2026-10-12T09:15:00.000Z"
}

Für ein Python-Paket, das dein Code importiert:

"reachability": {
  "verdict": "reachable",
  "level": "import",
  "reason_unknown": null,
  "engine": "python-imports",
  "engine_version": "1.1.0 (python 3.13.5)",
  "db_version": "2026-10-12T02:00:00.000Z",
  "advisory_id": "GHSA-9hjg-9r4m-mvj7",
  "evidence": {
    "manifest": "requirements.txt",
    "package": "requests",
    "version": "2.31.0",
    "mapping": "wheel requests-2.31.0-py3-none-any.whl",
    "provides": ["requests"],
    "frames": [{ "file": "app/main.py", "line": 2 }]
  },
  "computed_at": "2026-10-12T15:00:00.000Z"
}

Für ein Python-Paket, das nur über ein anderes Paket geladen wird, ist frames der Pfad, wie bei npm, und via nennt die Pakete darauf:

"evidence": {
  "manifest": "requirements.txt",
  "package": "idna",
  "version": "3.6",
  "mapping": "wheel idna-3.6-py3-none-any.whl",
  "provides": ["idna"],
  "via": ["requests@2.32.3"],
  "frames": [
    { "file": "app/main.py", "line": 2 },
    { "file": "requests/models.py", "line": 401, "package": "requests@2.32.3" }
  ]
}

Maven-Urteile haben dieselbe Form, mit engine jvm-imports, einem mapping, das das JAR nennt, und provides mit seinen Java-Paketen. Über ein anderes Paket nennt ein Frame in einem JAR die Quelldatei aus den Debug-Informationen der Klasse und die Zeile, in der die Klasse des nächsten Pakets verwendet wird. Die Zeile ist 0, wenn keine Anweisung sie verwendet, etwa bei einem implementierten Interface:

"evidence": {
  "manifest": "pom.xml",
  "package": "org.apache.commons:commons-text",
  "version": "1.9",
  "mapping": "jar commons-text-1.9.jar",
  "via": ["org.apache.commons:commons-configuration2@2.7"],
  "frames": [
    { "file": "src/main/java/app/App.java", "line": 3 },
    { "file": "org/apache/commons/configuration2/PropertiesConfiguration.java", "line": 1663, "package": "org.apache.commons:commons-configuration2@2.7" }
  ]
}

Für ein Python-Release nur mit sdist nennt mapping das sdist und wie die Namen gefunden wurden, zum Beispiel sdist pysaml2-4.4.0.tar.gz, package directories under src/.

Der erste npm-Frame ist die Zeile in deinem Repository. Die Frames danach sind Dateien und Zeilen in den Paketen auf dem Weg, jeweils mit ihrer Version benannt.

Ein Pull-Request-Befund trägt außerdem block_waived: "unreachable", wenn die Richtlinie, bei nicht erreichbaren Befunden nicht zu blockieren, ihn bei seinem letzten Scan durch fremforge/dep-scan gelassen hat, sonst null. Das ist kein Verwerfen.

Die Richtlinie selbst steht in dep_scan_unreachable_policy bei GET /orgs/{org}/security und wird mit PUT /orgs/{org}/security/dep-scan-unreachable-policy gesetzt (Scope policy:write):

{ "enabled": true, "repos": ["web", "acme/api"] }

enabled ist Pflicht. repos nimmt Namen von Repositorys deiner Organisation, bloß oder als org/name; lass es weg oder schicke [] für jedes Repository. Die Antwort enthält die gespeicherte Richtlinie, die vorherige und ob sie sich geändert hat.

Hänge ?reachability=reachable, unreachable oder unknown an, um nur diese zu listen. Die drei Werte teilen die Liste vollständig auf. Ohne den Parameter wird jeder Befund zurückgegeben. Belege enthalten nur Code-Orte, nie Code-Inhalte.

Hänge ?sort=risk an, um Befunde in Triage-Reihenfolge zu listen: Urteil (erreichbar, dann unbekannt oder nicht analysiert, dann nicht erreichbar), dann Schweregrad, dann bekannt ausgenutzt (Abhängigkeits- und Image-Befunde), dann EPSS bei Abhängigkeitsbefunden, dann die ältesten zuerst. Das Blättern mit offset ist in dieser Reihenfolge stabil. Ohne den Parameter oder mit sort=created werden Befunde wie bisher die neuesten zuerst gelistet.

Jeder SAST-Befund aus GET /orgs/{org}/code-security/sast/findings trägt seine Triage-Signale:

"triage": {
  "confidence": "lower",
  "reasons": ["test"],
  "location": "test",
  "dataflow": true,
  "dismissed_before": { "repo": 0, "org": 1, "days": 90 }
}

dataflow ist true bei einem Taint-Treffer, false bei einem reinen Muster-Treffer und null bei einem Befund, der vor Einführung des Signals erhoben wurde. Der nächste Scan des Repositorys füllt es aus.