Komponenteninventar
Das Komponenteninventar beantwortet zwei Fragen, ohne dass du eine einzige SBOM öffnen musst: Wo wird diese Komponente verwendet? und Welche verwundbaren Komponenten sind gerade im Einsatz? Es wird aus den SBOMs aufgebaut, die fremforge für deine Organisation vorhält, und ist für jede Organisation eingeschaltet.
Du findest es im Organisations-Admin unter Sicherheit › Komponenten, mit den Tabs Inventar, Verwundbar im Einsatz, Abgerufene Versionen, Deployments und Umgebungsregeln. Abgerufene Versionen listet die Paketversionen auf, die deine Konsumenten tatsächlich heruntergeladen haben, siehe Abgerufene Paketversionen. Deployments wird unten beschrieben.
Was indiziert wird
Jede aktuelle CycloneDX-SBOM wird in das Inventar eingelesen, eine Zeile pro Komponente und Einsatzort:
| Wo sie verwendet wird | Was als aktuell gilt |
|---|---|
| Ein Repository | die SBOM des Heads seines Standard-Branches |
| Ein Release | das neueste Release des Repositorys |
| Ein Container-Image | jeder Image-Digest, der in deiner Registry noch veröffentlicht ist |
| Ein Registry-Paket | jede Paketdatei, die nicht gelöscht wurde, sobald Paketrichtlinien für deine Organisation verfügbar sind |
| Eine hochgeladene SBOM | der neueste Upload jedes Artefaktnamens |
Eine neue SBOM aktualisiert nur, was sich geändert hat: Eine Komponente, die noch da ist, behält ihre Zeile und das Datum, an dem sie zum ersten Mal gesehen wurde, und eine Komponente, die verschwunden ist, wird als entfernt markiert. Entfernte Verwendungen werden 180 Tage lang aufbewahrt, sodass du weiterhin beantworten kannst, „wann wir aufgehört haben, X zu verwenden". Neue SBOMs werden bei ihrem Eintreffen indiziert; ein Hintergrundjob holt alle 30 Minuten nach, was verpasst wurde.
Suche
Jede Liste akzeptiert dieselben Filter, alle optional und kombinierbar:
| Parameter | Trifft auf |
|---|---|
q | den Komponentennamen, exakt oder als Präfix; ein Wert, der mit pkg: beginnt, trifft auf die Package URL |
purl | eine Package URL; ohne Version trifft sie auf jede Version |
range | ein Versionsbereich nach purl-spec, etwa vers:npm/>=4.17.0|<4.17.21; erfordert purl ohne Version |
ecosystem, version | das Ökosystem und eine exakte Version |
licence | eine SPDX-ID im Lizenzausdruck oder unknown |
environment | sandbox, development, test, staging, production oder unclassified |
environment_source | woher die Klasse stammt: deployment, reported oder rule |
subject_kind | repo, release, image, package oder artifact |
subject | der Name des Repositorys, Images, Pakets oder Artefakts |
current | true (Standard): jetzt im Einsatz; false liefert auch entfernte Verwendungen |
REST-API
Die API liegt unter https://frem.sh/_app/api/v1. Verwende ein API-Token der Organisation oder ein PAT mit dem Scope components:read; findings:read wird ebenfalls akzeptiert.
| Endpunkt | Liefert |
|---|---|
GET /orgs/{slug}/components | Komponenten im Einsatz, eine Zeile pro Package URL, mit der Anzahl der Einsatzorte, in welchen Umgebungen und welchen Arten der Verwendung |
GET /orgs/{slug}/components/usages | „Wo wird X verwendet": eine Zeile pro Komponente und Einsatzort |
GET /orgs/{slug}/components/{id} | eine Komponente |
GET /orgs/{slug}/components/{id}/usages | wo diese Komponente verwendet wird |
GET /orgs/{slug}/components/vulnerable | verwundbare Komponenten im Einsatz, verknüpft mit den offenen Befunden; min_severity=low|medium|high|critical |
GET /orgs/{slug}/components/vulnerable/summary | Anzahl verwundbarer Komponenten und Verwendungen, nach Schweregrad und Umgebung |
GET /orgs/{slug}/repos/{repo}/dependencies/paths | welche direkten Abhängigkeiten eine Komponente in das Repository bringen, siehe Abhängigkeitspfade |
GET /orgs/{slug}/components/environment-rules | deine Umgebungsregeln und Labels |
PUT /orgs/{slug}/components/environment-rules | die Regeln ersetzen (erfordert policy:write, wird im Audit-Log erfasst) |
Zum Beispiel jeder Ort, an dem lodash unter 4.17.21 im Einsatz ist:
curl -sS -H "Authorization: Bearer $FREMFORGE_TOKEN" \
"https://frem.sh/_app/api/v1/orgs/<org>/components/usages?purl=pkg:npm/lodash&range=vers:npm/%3C4.17.21"Paginierung
Listen werden per Cursor geblättert. Jede Antwort ist { "items": [...], "next_cursor": "..." }; übergib next_cursor als cursor für die nächste Seite, bis er null ist. limit liegt zwischen 1 und 500, Standard 100. Ein Cursor gehört zu dem Endpunkt, der ihn ausgegeben hat; ein anderer Endpunkt weist ihn mit invalid-cursor ab.
CSV-Export
Hänge format=csv an oder sende Accept: text/csv an eine beliebige Liste (/components, /components/usages, /components/{id}/usages, /components/vulnerable), und das gesamte Ergebnis kommt mit denselben Filtern und ohne Blättern als eine CSV-Datei zurück. Eine CSV enthält höchstens 200.000 Zeilen; darüber antwortet die API mit 413 too-many-rows, und du grenzt die Filter ein, blätterst durch das JSON oder nutzt den Datenexport. Die Admin-Seiten bieten denselben Export als Download-Schaltfläche.
Das vollständige Inventar, einschließlich entfernter Verwendungen, steht außerdem in jedem Datenexport als metadata/components.ndjson, siehe Exportschema.
Abhängigkeitspfade
Bei einer transitiven Abhängigkeit zeigt das Inventar, welche direkte Abhängigkeit sie hereinbringt, so wie der Abhängigkeitsgraph von GitHub. Unter Verwundbar im Einsatz steht in jeder Zeile Eingebracht über, gefolgt vom Pfad, zum Beispiel async@2.6.3 → lodash; auf der Seite einer Komponente zeigt die Spalte Abhängigkeit denselben Pfad oder Direkt, wenn das Repository selbst von der Komponente abhängt.
Der Pfad stammt aus dem Abhängigkeitsgraphen in einer SBOM. fremforge hält für jede indizierte SBOM eine kompakte Kopie dieses Graphen vor, sodass ein Pfad keinen SBOM-Download kostet. Pfade gibt es nur, wo eine SBOM Abhängigkeitskanten hat. Bei den SBOMs, die fremforge selbst erzeugt (syft, aus den Dateien im Repository), sind das:
| Ökosystem | Datei | Pfade |
|---|---|---|
| npm | package-lock.json, pnpm-lock.yaml, yarn.lock | ja |
| PyPI | uv.lock, poetry.lock | ja |
| Cargo | Cargo.lock | ja |
| Go | go.mod | ja: fremforge liest die go.mod jedes Moduls aus seinem Go-Modul-Cache, ohne Code aus deinem Repository auszuführen |
| Maven | pom.xml | nein: Jedes Paket, das die pom hereinzieht, steht im Inventar, aber ohne die Kanten dazwischen; pushe für Pfade eine CycloneDX-SBOM aus CI, siehe unten |
| Gradle | nein: pushe eine CycloneDX-SBOM aus CI, siehe unten | |
| NuGet | packages.lock.json | ja, für SBOMs, die seit dem 2026-10-10 erzeugt wurden (syft 1.54.1); ältere SBOMs zeigen keine, weil frühere syft-Versionen diese Kanten falsch geschrieben haben |
Composer, RubyGems, requirements.txt, Pipfile.lock | nein: Die SBOM hat keine Abhängigkeitskanten |
Wo es keinen Pfad gibt, zeigt die Zeile keinen Pfad statt einer Vermutung.
Wie eine direkte Abhängigkeit bestimmt wird, hängt von der Lockfile ab. Eine npm-package-lock.json, eine uv.lock, eine Cargo.lock und eine go.mod führen das Projekt selbst auf, und seine Abhängigkeiten sind die direkten (in go.mod die Anforderungen, die nicht mit // indirect markiert sind). pnpm-lock.yaml, yarn.lock, poetry.lock und packages.lock.json führen das Projekt nicht in der SBOM auf, daher gilt ein Paket als direkte Abhängigkeit, von dem nichts anderes in der Lockfile abhängt. Eine direkte Abhängigkeit, die zusätzlich ein anderes Paket benötigt, wird dann über dieses Paket angezeigt. Eine SBOM, deren Root-Komponente ihre eigenen Abhängigkeiten aufführt, wie es die CycloneDX-Build-Plugins schreiben, sagt selbst, welche direkt sind. Die API nennt in graph.direct_basis (project, roots oder declared), welche Regel angewendet wurde.
In der API antwortet GET /orgs/{slug}/repos/{repo}/dependencies/paths für den Head des Standard-Branches des Repositorys und für die SBOMs, die deine CI dafür gepusht hat (siehe unten), mit einem kürzesten Pfad pro direkter Abhängigkeit, die zur Komponente führt, kürzeste zuerst. Übergib purl (ohne Version trifft er auf jede Version) oder component_id, dazu limit (1 bis 100, Standard 20) und cursor für die nächste Seite. Jeder Pfad nennt in source (scan oder upload) und sbom_id, woher er stammt, und graph.sources listet jeden gelesenen Graphen auf. Die Einträge von /components/vulnerable und /components/usages enthalten via, die Package URL der direkten Abhängigkeit, und dependency_path, den kürzesten Pfad von ihr zur Komponente.
curl -sS -H "Authorization: Bearer $FREMFORGE_TOKEN" \
"https://frem.sh/_app/api/v1/orgs/<org>/repos/<repo>/dependencies/paths?purl=pkg:npm/lodash"Pfade für Maven, Gradle und Go aus CI
Einen Maven- oder Gradle-Abhängigkeitsbaum aufzulösen heißt, das Build-Werkzeug auszuführen, und das Build-Werkzeug führt Plugins aus deinen Build-Dateien aus. fremforge führt deinen Build nicht auf seinen Servern aus, daher kommt der Graph für diese Ökosysteme aus deiner eigenen CI: Erzeuge eine CycloneDX-SBOM mit dem CycloneDX-Plugin des Build-Werkzeugs, das den vollständig aufgelösten dependencies-Graphen schreibt, und pushe sie mit source_repo auf das Repository gesetzt. Die Pfad-API, via unter Verwundbar im Einsatz und die Komponentenseite verwenden dann diesen Graphen für das Repository. Pushe sie vom Standard-Branch, denn es zählt jeweils der neueste Upload jedes artifact_name.
Derselbe Push-Schritt funktioniert für alle drei. Das Secret FREMFORGE_API_TOKEN enthält ein Token mit dem Scope sboms:write; fremforge legt es in jedem neuen Repository an.
- name: Push the SBOM to fremforge
env:
FREMFORGE_API_TOKEN: ${{ secrets.FREMFORGE_API_TOKEN }}
run: |
set -euo pipefail
DIGEST=$(sha256sum "$SBOM" | cut -d' ' -f1)
curl -sS --fail-with-body \
-H "Authorization: Bearer $FREMFORGE_API_TOKEN" \
-F "sbom=@$SBOM" \
-F "format=cyclonedx-json" \
-F "sha256_digest=$DIGEST" \
-F "artifact_name=${GITHUB_REPOSITORY#*/}-cyclonedx" \
-F "artifact_version=$GITHUB_SHA" \
-F "source_repo=$GITHUB_REPOSITORY" \
-F "repo_full_name=$GITHUB_REPOSITORY" \
-F "commit_sha=$GITHUB_SHA" \
-F "git_ref=$GITHUB_REF" \
"$GITHUB_SERVER_URL/_app/api/v1/orgs/$GITHUB_REPOSITORY_OWNER/sboms"Maven, mit dem cyclonedx-maven-plugin. An deiner pom.xml muss sich nichts ändern:
name: sbom
on:
push:
branches: [main]
jobs:
sbom:
runs-on: fremforge
env:
SBOM: target/bom.json
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: CycloneDX SBOM with the full dependency graph
run: mvn -B -q org.cyclonedx:cyclonedx-maven-plugin:2.9.1:makeBom -DoutputFormat=json -DoutputName=bom -DschemaVersion=1.6
# then the push step aboveBei einem Build mit mehreren Modulen verwende stattdessen das Goal makeAggregateBom; seine SBOM ist target/bom.json des obersten Projekts.
Gradle, mit dem CycloneDX-Gradle-Plugin. Füge das Plugin zu build.gradle hinzu:
plugins {
id 'org.cyclonedx.bom' version '3.5.1'
}und erzeuge die SBOM im Job, mit SBOM: build/reports/cyclonedx-direct/bom.json:
- name: CycloneDX SBOM with the full dependency graph
run: gradle cyclonedxDirectBomGo, mit cyclonedx-gomod. fremforge findet Pfade für Go bereits selbst (siehe Tabelle oben). Pushe aus CI, wenn fremforge deine Module nicht abrufen kann, zum Beispiel private Module, die sein Go-Modul-Cache nicht erreicht, mit SBOM: bom.json:
- uses: actions/setup-go@v5
with:
go-version: '1.27'
- name: CycloneDX SBOM with the module graph
run: |
go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@v1.9.0
"$(go env GOPATH)/bin/cyclonedx-gomod" mod -json -output "$SBOM" .Die gepushte SBOM wird außerdem als eigenes hochgeladenes Artefakt indiziert, sodass ihre Komponenten im Inventar sowohl unter ihrem artifact_name als auch unter dem Repository erscheinen. Ein Abhängigkeits-Scan einer Gradle-Build-Datei sieht nur die Abhängigkeiten, die die Datei deklariert, und einer einer pom.xml sieht, worauf ihre poms auflösen, nicht, was ein Plugin ändert. Daher wird jede Maven-Komponente eines gepushten Graphen, einschließlich der transitiven, gegen dieselbe Advisory-Datenbank abgeglichen, die die Scans verwenden, und jeder Treffer ist ein Abhängigkeitsbefund des in source_repo genannten Repositorys. Diese Befunde haben das Manifest sbom:<artifact_name>. Sie erscheinen unter Verwundbar im Einsatz mit ihrem Pfad, bei den Abhängigkeitsbefunden auf den Sicherheitsseiten und in der Befund-API, und sie werden wie jeder andere Befund verworfen. Sie werden neu berechnet, wenn die SBOM gepusht wird, nach jedem Scan des Standard-Branches des Repositorys und nach jeder Aktualisierung der Advisory-Datenbank, sodass eine neue Advisory einen Befund hinzufügt und eine zurückgezogene ihn entfernt. Eine Advisory, die der eigene Scan des Repositorys bereits meldet, wird nicht doppelt aufgeführt. Es sind Befunde des Standard-Branches: Eine gepushte SBOM ändert den Status fremforge/dep-scan eines Pull Requests nicht. Ein so gepushter NuGet-Graph wird so verwendet, wie er geschrieben ist, es sei denn, syft vor Version 1.54.1 hat ihn geschrieben.
Umgebungsklassen
Jede Verwendung kann eine Umgebungsklasse tragen: sandbox, development, test, staging oder production. Sie stammt aus einer von drei Quellen, und die erste, die zutrifft, gewinnt:
deployment: Ein Deployment, das deine CI/CD mitPOST /orgs/{slug}/repos/{repo}/deploymentsgemeldet hat und dessen letzter Statussuccessist, nennt den Image-Digest, den Commit, den Release-Tag oder die Paketversion der Verwendung. Tun das mehrere, gewinnt die höchste Klasse. Die Verwendungszeile enthältdeployment_idunddeployment_environment. Siehe die API-Referenz.reported: Ein SBOM-Upload hat ein eigenesenvironmentangegeben.rule: die erste passende Regel unter Umgebungsregeln, die auf die Art der Verwendung, ein Repository, einen Tag, ein Image oder einen Artefaktnamen passt.
Die Klasse dient der Suche und Berichterstattung; sie ändert weder die Aufbewahrung noch eine Sperre.
Deployments
Der Tab Deployments listet die Deployments auf, die deine CI/CD gemeldet hat, die neuesten zuerst: das Repository, den Umgebungsnamen und seine Klasse, den Zustand (ein Deployment, dessen letzter Status success ist, wird als aktuell deployt markiert), den Commit oder Ref, die genannten Image-Digests und Paketversionen und wer es gemeldet hat (ein CI-Job mit seinem Lauf, ein Registry-Robot, ein Benutzer oder ein API-Token). Filtere nach Repository, Umgebungsname, Umgebungsklasse und Zustand, oder setze den Haken bei Nur aktuell deployt. Nächste Seite und Erste Seite blättern durch die Liste. Dieselbe Liste gibt es in der API unter GET /orgs/{slug}/deployments/reported (Scope components:read), und jeder Datenexport enthält sie als metadata/deployments.ndjson mit dem Statusverlauf jedes Deployments, siehe Exportschema.
Verwandte Themen
- SBOMs: woher die SBOMs stammen.
- Compliance-Bericht: Sein Abschnitt „riskanteste Komponenten" liest das Inventar.
- Abgerufene Paketversionen: welche verwundbaren Versionen deine Konsumenten tatsächlich herunterladen, unter
GET /orgs/{slug}/components/pulled.