Gå til hovedindhold

Licensscanning

Licensscanning svarer på spørgsmålet hvad må jeg udgive og supplerer SBOM’ens hvad er der i dette image og afhængighedsscanningens hvad er sårbart. fremforge kører Trivys licensdetektion på hver PR, klassificerer licensen for hver opløst afhængighed i en alvorlighedskategori fra SPDX-politikken og viser resultatet ved PR’en og på et særskilt dashboard for organisationen. Den er slået til som standard for alle organisationer — der er intet at aktivere.

Sådan virker det

fremforges centrale scanner (den samme, der kører SAST, afhængighedsscanning og image-scanning) læser licensen for hver afhængighed, dine lockfiler opløser, og kører Trivys detektion af licensfiler over dit repositorys egne LICENSE/COPYING-filer ved hver PR. Den kører på fremforges egne runners — intet installeres i dit repository. I modsætning til SAST og afhængighedsscanning, der sender en liste med kun problemer, sender licensscanningen en fuld licensoversigt: ét fund pr. (pakke × licens) på tværs af alle opløste afhængigheder. Workflowet sender derefter oversigten til fremforge med POST:

POST https://frem.sh/_app/api/v1/license-scan/findings

Runnerens PAT skal have scopet findings:write (udstedes pr. repository af runner-controlleren, når workflowet installeres). Ved en vellykket indlæsning gør fremforge følgende:

  1. Gemmer fundene. Én række pr. fund i license_scan_findings. Hver scanning erstatter den tidligere scanning for samme (tenant, repo, pr_number) fuldstændigt — en PR, der fjerner en afhængighed, holder op med at vise dens forældede rækker. Push-scanninger (pr_number null) har deres egen kategori, så de ikke erstatter PR-scanninger på kryds.
  2. Skriver en PR-kommentar, der opsummerer fundene (alvorlighed, licens, pakke, manifest), via Forgejos issues-API.
  3. Sætter commit-statussen fremforge/license-scan på PR’ens head-SHA — success, når der kun er fund til orientering, eller alle er på tilladelseslisten, og failure, når politikkens gate rammes.

Kommentaren og statussen i Forgejo er best-effort: et nedbrud i Forgejo logges og nedgraderes til orientering, men får aldrig indlæsningen til at fejle. De gemte fund er sandheden; visningen i PR’en er et bekvemmelighedslag.

Hvor afhængighedernes licenser kommer fra

Intet installeres: licenserne læses fra registry-metadata for præcis den version, hver lockfil fastlåser. For npm, PyPI, Go og Maven læses metadataene gennem din organisations dependency-proxy på scanningstjenestens interne rute, eller gennem fremforges delte scanningscache, når din organisation ikke har nogen proxy; kun når ingen af dem kan svare, læses de fra det offentlige registry gennem fremforges egress-proxy. Licenser fra NuGet, crates.io, RubyGems og Packagist læses fra det offentlige registry gennem egress-proxyen. fremforges tidligere pakkespejle i clusteret er udfaset.

ØkosystemKildeHvad der læses
npm (lockfiler fra npm / pnpm / yarn / bun)registry.npmjs.org, gennem dependency-proxyenpakkens felt license
Go (go.mod)proxy.golang.org, gennem dependency-proxyen; private moduler (frem.sh, din angivne GOPRIVATE) forespørges aldrigmodulets LICENSE- / COPYING-fil i roden, klassificeret med den samme detektion af licensfiler som dine egne filer (Go har ingen licensmetadata)
Maven (pom.xml, Gradle-lockfiler)Maven Central, gennem dependency-proxyenPOM’ens <licenses>, med relocations og forælder-POM’er fulgt
NuGet (packages.lock.json)nuget.org, gennem egress-proxyenpakkens licensudtryk eller en genkendelig licens-URL
PyPI (requirements.txt, Poetry, uv)pypi.org, gennem dependency-proxyenudgivelsens JSON-metadata (license_expression, en kort license, licens-classifiers)
crates.io, RubyGems, Packagistdet offentlige registry, gennem egress-proxyenregistry’ets licensfelt pr. version

Licensnavne i fritekst (GPL v3, GNU AFFERO GPL 3.0, Apache License, Version 2.0, …) oversættes til SPDX-id’er. Alt, der ikke kan læses med sikkerhed, rapporteres som unknown og vises til gennemgang; det gættes aldrig til at være permissivt.

Når en kilde er nede

Hvis et spejl eller registry ikke svarer (netværksfejl, timeout, 5xx), bliver de berørte pakker hverken læst som rene eller får lov at blokere: statussen fremforge/license-scan beholder det, resten af scanningen gav, og tilføjer lookup-unavailable for N package(s), re-scan queued. fremforge kører automatisk scanningen igen med få minutters mellemrum, indtil kilden svarer, og noten forsvinder.

Alvorlighedskategorier

Licensscanning bruger et ordforråd med 7 kategorier for alvorlighed (ikke de 4 niveauer CRITICAL/HIGH/… fra CVE-scanning), der svarer til Trivys klassificering efter SPDX-politik — ordnet fra mindst til mest bebyrdende:

KategoriBetydningEksempler på licenser
unknownLicensen kunne ikke bestemmes (vises stadig til gennemgang)NOASSERTION
unencumberedSvarer til public domainCC0-1.0, Unlicense
permissiveFrit brug, minimale forpligtelser—
noticePermissiv med forpligtelser til kreditering / meddelelseMIT, BSD-3-Clause, Apache-2.0, ISC
reciprocalSvag copyleft — ændringer i selve biblioteket delesLGPL-2.1, LGPL-3.0, MPL-2.0, EPL-2.0, CDDL-1.0, GPL-2.0 WITH Classpath-exception-2.0
restrictedStærk copyleftGPL-2.0, GPL-3.0, CC-BY-SA-4.0
forbiddenNetværks-copyleft / source-availableAGPL-3.0, SSPL-1.0, BUSL-1.1, CC-BY-NC-4.0

LGPL er reciprocal i fremforge (Trivys egen tabel placerer den i restricted): et program kan linke til et LGPL-bibliotek uden selv at blive LGPL, så det er svag copyleft og blokerer ikke ved standardtærsklen.

Politikindstillinger

Én licenspolitik siden 2026-10-15. Listerne, reglerne for ukendte og flere licenser og blokeringsalvorligheden redigeres under Sikkerhed › Politikker › Licenspolitik, sammen med licensreglerne for pakkedownloads. Se Licenspolitik. Sikkerhed › Fund › Licenser beholder kontakten til at slå den til og fra og tilsidesættelserne pr. repository. API-felterne nedenfor virker stadig og ændrer kun pull requests.

Konfigurér på siden Licenspolitik, gennem API’et (PUT /orgs/<org>/code-security/licenses/settings, kun pull requests) eller som kode med Terraform- og OpenTofu-modulet:

  • Slået til — når den er slået fra, svarer indlæsningen 202 {accepted: 0, status: 'disabled'} (workflowet kører stadig, fundene kasseres bare). Slået til som standard.
  • Blokeringsalvorlighed — tærsklen, hvor et fund på eller over den blokerer merge. Standard er restricted (siden 2026-09-29; den var forbidden, som lod GPL-afhængigheder slippe igennem til orientering): stærk copyleft og derover blokerer, svag copyleft forbliver til orientering. En licens, der ikke står på nogen af listerne nedenfor, vurderes efter denne tærskel. Kombinér med branch protection, der kræver tjekket fremforge/license-scan, for rent faktisk at blokere merge.
  • Licenspolitik — eksplicitte lister og to regler, beskrevet i næste afsnit.

Fund i forbidden (→ critical) eller restricted (→ high), eller afvist af listen over afviste licenser, som en scanning har tilføjet, og som ikke er afvist, udløser også hooket til sikkerhedsalarmer i realtid; lavere kategorier er kun til orientering.

Licenspolitik

Hvert fund afgøres pr. SPDX-operand, med samme læsning som pakkepolitikken bruger: i MIT OR GPL-3.0-only kan forbrugeren vælge, så den mindst begrænsende operand afgør; i Apache-2.0 AND GPL-2.0-only gælder begge, så den mest begrænsende operand afgør. Indlejrede parenteser, WITH-undtagelser (GPL-2.0-only WITH Classpath-exception-2.0) og LicenseRef-…-id’er læses, som SPDX definerer dem.

IndstillingAPI-feltStandardVirkning
Tilladte licenserallowlisted_license_idstomEn operand på listen er tilladt: fundet afvises ved indlæsningen (actor tenant_allowlist), uanset kategori.
Afviste licenserdenied_license_idstomEn operand på listen blokerer, uanset kategori. Afvist vinder over tilladt for samme id.
Licenser, der giver advarselwarned_license_idstomEn operand på listen er til orientering: rapporteret, aldrig blokerende, uanset kategori.
Ukendte licenserunknown_actionthresholdEn licens uden SPDX-id, NOASSERTION, NONE, UNKNOWN, en streng, der ikke er et SPDX-udtryk, eller et id, fremforge ikke kan klassificere (som et LicenseRef-…, der ikke står på en liste): threshold vurderer den som kategorien unknown under blokeringsalvorligheden; allow afviser fundet, warn rapporterer det, deny blokerer det.
Flere licensermultiple_modeallEn komponent, der angiver flere licenser (separate fund, ikke ét udtryk): all vurderer hver licens for sig, så enhver af dem kan blokere; any lader den mindst begrænsende afgøre for dem alle.

Listernes poster er SPDX-id’er (MIT, LicenseRef-acme) eller et id med sin undtagelse (GPL-2.0-only WITH Classpath-exception-2.0), og der skelnes ikke mellem store og små bogstaver; GPL-2.0+ matcher GPL-2.0-or-later. En post for grundlicensen dækker den med enhver undtagelse; en post for parret dækker kun parret. Op til 100 poster pr. liste. En PUT erstatter indstillingerne: et felt, der udelades, får sin standardværdi.

Standardværdierne ændrer intet. Med tomme lister over afviste og advarende licenser, unknown_action: threshold og multiple_mode: all afgøres hvert fund præcis, som blokeringsalvorligheden og tilladelseslisten afgjorde det, før denne politik fandtes. Den eneste forskel er selve tilladelseslisten, der nu matcher operander: MIT OR GPL-3.0-only består med en tilladelsesliste, der indeholder MIT.

Hvorfor et fund blokerer

På en pull request blokerer kun fund, som pull requesten tilføjer: en pakke og licens, som branchen allerede har, blokerer ikke.

Hvert fund bærer afgørelsen som policy i fund-API’et (GET /orgs/<org>/code-security/licenses/findings), og dashboardet viser den i kolonnen Politikkens afgørelse:

{
  "license_id": "MIT OR GPL-3.0-only",
  "policy": {
    "action": "allow",
    "rule": "allow_list",
    "decided_by": ["MIT"],
    "operands": [
      { "operand": "MIT", "action": "allow", "rule": "allow_list", "matched": "MIT" },
      { "operand": "GPL-3.0-only", "action": "block", "rule": "deny_list", "matched": "GPL-3.0-only" }
    ],
    "why": "allowed: MIT is on the allow list (OR takes the least restrictive operand)"
  }
}

action er allow, warn eller block; rule er allow_list, deny_list, warn_list, threshold, below_threshold, unknown, multiple_any eller exception. PR-kommentaren viser hvert blokerende fund med sin årsag, og statussen fremforge/license-scan nævner reglerne (2 finding(s) blocked by the licence policy (1 denied, 1 at or above restricted)).

For at afprøve en politik, før en PR gør det, afgør POST /orgs/<org>/code-security/licenses/evaluate en liste af licenser uden at skrive noget:

curl -sS -X POST -H "Authorization: Bearer $FREMFORGE_TOKEN" -H 'Content-Type: application/json' \
  -d '{"licenses":[{"license_id":"MIT OR GPL-3.0-only"},{"license_id":"Apache-2.0 AND GPL-2.0-only"}]}' \
  https://frem.sh/_app/api/v1/orgs/<org>/code-security/licenses/evaluate

Tilsidesættelser pr. repository

Et repository kan tilsidesætte hvert af de fem politikfelter: PUT /orgs/<org>/repos/<repo>/code-security/licenses/settings med de felter, der skal sættes. Et felt, der er sat, erstatter organisationens værdi for det repository (en liste erstatter organisationens liste; et tomt array er en værdi); et felt, der mangler eller er null, arves. GET på samme sti viser tilsidesættelsen og den gældende politik, DELETE fjerner den. I konsollen findes tilsidesættelserne under Tilsidesættelser pr. repository på Sikkerhed › Politikker › Licenspolitik.

Licensundtagelser for én komponent

For at acceptere én licens for én komponent — for eksempel et GPL-værktøj, som din juridiske afdeling har godkendt — anmoder du om en undtagelse (POST /orgs/<org>/exceptions med kind: package, eller i konsollen) med omfanget component, reglen licence, komponentens purl uden version (pkg:npm/left-pad, pkg:pypi/requests, pkg:maven/org.example:lib) og licens-id’et som selektor (lad selektoren være tom for enhver licens for den komponent). Det er den samme undtagelse som for pakkepolitikker: en begrundelse, en obligatorisk udløbsdato på højst et år og godkendelse af en ejer eller navngiven godkender, der ikke er den, som anmoder. Når den er godkendt (POST /orgs/<org>/exceptions/<id>/approve, af en anden end den, som anmoder), afviser den næste scanning af et hvilket som helst repository de matchende fund (actor licence-exception:<id>, dismissal_approved_by godkenderen, årsag med begrundelsen), indtil undtagelsen udløber (fundet genåbnes den dag) eller tilbagekaldes (den næste scanning genåbner det).

Afvisning af fund

En administrator i organisationen kan afvise enkelte fund (med en påkrævet årsag, der skrives i revisionsloggen) fra fanen Licenser. Manuelle afvisninger føres videre gennem genscanningen, der erstatter ved indlæsning, med nøglen (licens-id, pakke, manifeststi) — en genscanning af en PR genopliver ikke et fund, som en administrator allerede har accepteret. En afvisning kan have en valgfri udløbsdato, hvorefter fundet genåbnes af sig selv — se hvornår et fund lukkes. Afvisninger foretaget af licenspolitikken (listen over tilladte, unknown allow, multiple_mode: any, en undtagelse) føres ikke videre; de udledes igen af indstillingerne ved hver scanning, så en ændring af politikken får virkning ved næste scanning.

Hvor fund vises

Sikkerhed › Fund › Licenser viser aktive fund og nylige afvisninger. Hvert fund viser alvorlighedskategorien, SPDX-licens-id’et, ecosystem:package, manifeststien og politikkens afgørelse med årsag. PR-kommentaren linker tilbage til dette dashboard.

Opbevaring

Fund følger revisionslogens opbevaringspolitik pr. tenant, ligesom de andre kodesikkerhedsscannere. Fund fra lukkede PR’er ryddes af det daglige job /jobs/license-scan-closed-pr-cleanup, da en lukket PR aldrig scannes igen.

Se også

  • OSV-anbefalinger — scanning af afhængigheder for CVE’er (sårbarheds-supplementet til denne licens-visning).
  • SBOM’er — pakkeoversigten, som licenserne knyttes til.
  • Image-scanning — søsterscanneren, der deler den samme centrale scanningskørsel og indlæsningsmønster med findings:write.
  • Sikkerhedsfunktioner i overblik — den fulde kontrolmatrix.