Naar de hoofdinhoud

Componenteninventaris

De componenteninventaris beantwoordt twee vragen zonder dat je één SBOM hoeft te openen: waar wordt deze component gebruikt, en welke kwetsbare componenten zijn op dit moment in gebruik. Hij wordt opgebouwd uit de SBOM’s die fremforge voor je organisatie bewaart en staat voor elke organisatie aan.

Je vindt hem in het organisatiebeheer onder Beveiliging › Componenten, met de tabbladen Inventaris, Kwetsbaar in gebruik, Opgehaalde versies, Deployments en Omgevingsregels. Opgehaalde versies toont de packageversies die je afnemers daadwerkelijk hebben gedownload, zie Opgehaalde packageversies. Deployments wordt hieronder beschreven.

Wat wordt geïndexeerd

Elke actuele CycloneDX-SBOM wordt in de inventaris ingelezen, met één rij per component en plek waar die wordt gebruikt:

Waar het wordt gebruiktWat als actueel telt
Een repositoryde SBOM van de head van de standaardbranch
Een releasede nieuwste release van de repository
Een container-imageelke image-digest die nog in je registry is gepubliceerd
Een package in de registryelk packagebestand dat niet is verwijderd, zodra packagebeleid beschikbaar is voor je organisatie
Een geüploade SBOMde nieuwste upload van elke artefactnaam

Een nieuwe SBOM werkt alleen bij wat er is veranderd: een component die er nog is, houdt zijn rij en de datum waarop hij voor het eerst is gezien, en een component die is verdwenen, wordt als verwijderd gemarkeerd. Verwijderd gebruik wordt 180 dagen bewaard, zodat je nog steeds kunt beantwoorden ‘wanneer zijn we gestopt met X’. Nieuwe SBOM’s worden geïndexeerd zodra ze binnenkomen; een achtergrondjob haalt elke 30 minuten in wat is gemist.

Zoeken

Elke lijst accepteert dezelfde filters, allemaal optioneel en te combineren:

ParameterKomt overeen met
qde naam van de component, exact of als prefix; een waarde die met pkg: begint, wordt vergeleken met de package-URL
purleen package-URL; zonder versie komt hij overeen met elke versie
rangeeen versiebereik volgens de purl-spec, zoals vers:npm/>=4.17.0|<4.17.21; vereist purl zonder versie
ecosystem, versionhet ecosysteem, en een exacte versie
licenceeen SPDX-id in de licentie-expressie, of unknown
environmentsandbox, development, test, staging, production of unclassified
environment_sourcewaar de klasse vandaan komt: deployment, reported of rule
subject_kindrepo, release, image, package of artifact
subjectde naam van de repository, het image, de package of het artefact
currenttrue (de standaard): nu in gebruik; false geeft ook verwijderd gebruik terug

REST API

De API staat onder https://frem.sh/_app/api/v1. Gebruik een API-token van de organisatie of een PAT met de scope components:read; findings:read wordt ook geaccepteerd.

EndpointGeeft terug
GET /orgs/{slug}/componentscomponenten in gebruik, één rij per package-URL, met op hoeveel plekken elke component wordt gebruikt, in welke omgevingen en voor welke soorten gebruik
GET /orgs/{slug}/components/usages‘waar wordt X gebruikt’: één rij per component en plek
GET /orgs/{slug}/components/{id}één component
GET /orgs/{slug}/components/{id}/usageswaar die component wordt gebruikt
GET /orgs/{slug}/components/vulnerablekwetsbare componenten in gebruik, gekoppeld aan de open bevindingen; min_severity=low|medium|high|critical
GET /orgs/{slug}/components/vulnerable/summaryaantallen kwetsbare componenten en gebruiken, per ernst en omgeving
GET /orgs/{slug}/repos/{repo}/dependencies/pathsvia welke directe afhankelijkheden een component in de repository terechtkomt, zie Afhankelijkheidspaden
GET /orgs/{slug}/components/environment-rulesje omgevingsregels en labels
PUT /orgs/{slug}/components/environment-rulesde regels vervangen (vereist policy:write, vastgelegd in het auditlog)

Bijvoorbeeld elke plek waar lodash lager dan 4.17.21 in gebruik is:

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"

Paginering

Lijsten worden gepagineerd met een cursor. Elk antwoord is { "items": [...], "next_cursor": "..." }; geef next_cursor terug als cursor voor de volgende pagina, totdat hij null is. limit is 1 tot 500 en is standaard 100. Een cursor hoort bij het endpoint dat hem heeft uitgegeven; een ander endpoint weigert hem met invalid-cursor.

CSV-export

Voeg format=csv toe, of stuur Accept: text/csv, bij elke lijst (/components, /components/usages, /components/{id}/usages, /components/vulnerable), en het hele resultaat komt terug als één CSV-bestand met dezelfde filters, zonder paginering. Een CSV bevat hooguit 200.000 rijen; daarboven antwoordt de API met 413 too-many-rows, en dan verfijn je de filters, blader je door de JSON, of gebruik je de data-export. De beheerpagina’s hebben dezelfde export als downloadknop.

De volledige inventaris, inclusief verwijderd gebruik, zit ook in elke data-export als metadata/components.ndjson, zie Exportschema.

Afhankelijkheidspaden

Voor een transitieve afhankelijkheid toont de inventaris via welke directe afhankelijkheid hij binnenkomt, zoals de dependency graph van GitHub dat doet. Op Kwetsbaar in gebruik staat bij elke rij Binnengekomen via gevolgd door het pad, bijvoorbeeld async@2.6.3 → lodash; op de pagina van een component toont de kolom Afhankelijkheid hetzelfde pad, of Direct wanneer de repository zelf van de component afhangt.

Het pad komt uit de afhankelijkheidsgraaf in een SBOM. fremforge bewaart een compacte kopie van die graaf voor elke SBOM die het indexeert, zodat een pad geen SBOM-download kost. Paden bestaan alleen waar een SBOM afhankelijkheidsrelaties bevat. Bij de SBOM’s die fremforge zelf genereert (syft, uit de bestanden in de repository) is dat:

EcosysteemBestandPaden
npmpackage-lock.json, pnpm-lock.yaml, yarn.lockja
PyPIuv.lock, poetry.lockja
CargoCargo.lockja
Gogo.modja: fremforge leest de go.mod van elke module uit zijn Go-modulecache, zonder code uit je repository uit te voeren
Mavenpom.xmlnee: elke package die de pom binnenhaalt, staat in de inventaris, maar zonder de relaties ertussen; push voor paden een CycloneDX-SBOM vanuit CI, zie hieronder
Gradlenee: push een CycloneDX-SBOM vanuit CI, zie hieronder
NuGetpackages.lock.jsonja, voor SBOM’s die sinds 2026-10-10 zijn gegenereerd (syft 1.54.1); oudere SBOM’s tonen er geen, omdat eerdere syft-versies deze relaties verkeerd wegschreven
Composer, RubyGems, requirements.txt, Pipfile.locknee: de SBOM bevat geen afhankelijkheidsrelaties

Waar er geen pad is, toont de rij geen pad in plaats van een gok.

Hoe wordt bepaald wat een directe afhankelijkheid is, hangt af van het lockbestand. Een npm-package-lock.json, een uv.lock, een Cargo.lock en een go.mod vermelden het project zelf, en de afhankelijkheden daarvan zijn de directe (in go.mod de requirements die niet met // indirect zijn gemarkeerd). pnpm-lock.yaml, yarn.lock, poetry.lock en packages.lock.json vermelden het project niet in de SBOM, dus geldt als directe afhankelijkheid een package waarvan niets anders in het lockbestand afhangt. Een directe afhankelijkheid die ook door een andere package wordt vereist, wordt dan via die package getoond. Een SBOM waarvan de rootcomponent zijn eigen afhankelijkheden vermeldt, zoals de CycloneDX-buildplugins die wegschrijven, geeft zelf aan welke direct zijn. De API vermeldt in graph.direct_basis welke regel is toegepast (project, roots of declared).

In de API antwoordt GET /orgs/{slug}/repos/{repo}/dependencies/paths voor de head van de standaardbranch van de repository, en voor de SBOM’s die je CI ervoor heeft gepusht (hieronder), met één kortste pad per directe afhankelijkheid die naar de component leidt, kortste eerst. Geef purl mee (zonder versie komt hij overeen met elke versie) of component_id, plus limit (1 tot 100, standaard 20) en cursor voor de volgende pagina. Elk pad vermeldt in source (scan of upload) en sbom_id waar het vandaan komt, en graph.sources toont elke graaf die is gelezen. De items van /components/vulnerable en /components/usages bevatten via, de package-URL van de directe afhankelijkheid, en dependency_path, het kortste pad daarvandaan naar de component.

curl -sS -H "Authorization: Bearer $FREMFORGE_TOKEN" \
  "https://frem.sh/_app/api/v1/orgs/<org>/repos/<repo>/dependencies/paths?purl=pkg:npm/lodash"

Paden voor Maven, Gradle en Go vanuit CI

Een afhankelijkheidsboom van Maven of Gradle oplossen betekent de buildtool draaien, en de buildtool voert plugins uit je buildbestanden uit. fremforge draait je build niet op zijn servers, dus voor deze ecosystemen komt de graaf uit je eigen CI: genereer een CycloneDX-SBOM met de CycloneDX-plugin van de buildtool, die de volledige opgeloste dependencies-graaf wegschrijft, en push hem met source_repo ingesteld op de repository. De paden-API, via op Kwetsbaar in gebruik en de componentpagina gebruiken dan die graaf voor de repository. Push vanaf de standaardbranch, want de nieuwste upload van elke artifact_name is degene die telt.

Dezelfde pushstap werkt voor alle drie. Het secret FREMFORGE_API_TOKEN bevat een token met de scope sboms:write; fremforge maakt het aan in elke nieuwe repository.

      - 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, met de cyclonedx-maven-plugin. Aan je pom.xml hoeft niets te veranderen:

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 above

Gebruik voor een build met meerdere modules in plaats daarvan het goal makeAggregateBom; de SBOM daarvan is target/bom.json van het hoofdproject.

Gradle, met de CycloneDX Gradle plugin. Voeg de plugin toe aan build.gradle:

plugins {
    id 'org.cyclonedx.bom' version '3.5.1'
}

en genereer de SBOM in de job, met SBOM: build/reports/cyclonedx-direct/bom.json:

      - name: CycloneDX SBOM with the full dependency graph
        run: gradle cyclonedxDirectBom

Go, met cyclonedx-gomod. fremforge vindt paden voor Go al zelf (zie de tabel hierboven). Push vanuit CI wanneer fremforge je modules niet kan ophalen, bijvoorbeeld privémodules die zijn Go-modulecache niet kan bereiken, met 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" .

De gepushte SBOM wordt ook als eigen geüpload artefact geïndexeerd, zodat de componenten ervan in de inventaris verschijnen onder de artifact_name en onder de repository. Een afhankelijkheidsscan van een Gradle-buildbestand ziet alleen de afhankelijkheden die het bestand declareert, en een scan van een pom.xml ziet waar de poms naar oplossen, niet wat een plugin verandert. Daarom wordt elke Maven-component van een gepushte graaf, ook de transitieve, vergeleken met dezelfde advisorydatabase die de scans gebruiken, en elke overeenkomst is een afhankelijkheidsbevinding van de repository die in source_repo staat. Deze bevindingen hebben het manifest sbom:<artifact_name>. Ze verschijnen met hun pad op Kwetsbaar in gebruik, bij de afhankelijkheidsbevindingen op de Beveiliging-pagina’s en in de bevindingen-API, en je negeert ze zoals elke andere bevinding. Ze worden opnieuw berekend wanneer de SBOM wordt gepusht, na elke scan van de standaardbranch van de repository, en na elke vernieuwing van de advisorydatabase, zodat een nieuwe advisory een bevinding toevoegt en een ingetrokken advisory er een weghaalt. Een advisory die de eigen scan van de repository al meldt, wordt niet dubbel vermeld. Het zijn bevindingen van de standaardbranch: een gepushte SBOM verandert de status fremforge/dep-scan van een pull request niet. Een NuGet-graaf die op deze manier wordt gepusht, wordt gebruikt zoals hij is geschreven, tenzij syft ouder dan 1.54.1 hem heeft geschreven.

Omgevingsklassen

Elk gebruik kan een omgevingsklasse hebben: sandbox, development, test, staging of production. Die komt uit een van drie bronnen, en de eerste die van toepassing is, wint:

  1. deployment: een deployment die je CI/CD heeft gemeld met POST /orgs/{slug}/repos/{repo}/deployments, waarvan de laatste status success is, noemt de image-digest, commit, release-tag of packageversie van het gebruik. Als meerdere dat doen, wint de hoogste klasse. De gebruiksrij bevat deployment_id en deployment_environment. Zie de API-referentie.
  2. reported: een SBOM-upload gaf zijn eigen environment op.
  3. rule: de eerste overeenkomende regel onder Omgevingsregels, die kijkt naar de soort gebruik, een repository, een tag, een image of een artefactnaam.

De klasse is bedoeld voor zoeken en rapporteren; ze verandert geen bewaartermijn of poort.

Deployments

Het tabblad Deployments toont de deployments die je CI/CD heeft gemeld, nieuwste eerst: de repository, de naam van de omgeving en de klasse ervan, de status (een deployment waarvan de laatste status success is, wordt gemarkeerd als nu gedeployed), de commit of ref, de image-digests en packageversies die hij noemt, en wie hem heeft gemeld (een CI-job met zijn run, een registryrobot, een gebruiker of een API-token). Filter op repository, omgevingsnaam, omgevingsklasse en status, of vink Alleen nu gedeployed aan. Met Volgende pagina en Eerste pagina blader je door de lijst. Dezelfde lijst staat in de API op GET /orgs/{slug}/deployments/reported (scope components:read), en elke data-export bevat hem als metadata/deployments.ndjson met de statusgeschiedenis van elke deployment, zie Exportschema.

Gerelateerd

  • SBOM’s: waar de SBOM’s vandaan komen.
  • Compliancerapport: de sectie ‘meest riskante componenten’ leest de inventaris.
  • Opgehaalde packageversies: welke kwetsbare versies je afnemers daadwerkelijk downloaden, op GET /orgs/{slug}/components/pulled.