Nåbarhed
En advisory om en afhængighed siger, at en pakkeversion er sårbar. Den siger ikke, om dit program kan nå den sårbare kode. Nåbarhed besvarer det for Go ud fra de binærfiler, du faktisk leverer, og ud fra dit repositorys kode for JavaScript og TypeScript (npm) og, på importniveau, Python (PyPI) og Java og Kotlin (Maven). Den viser dig hvorfor. For Go analyseres også dit repositorys egen kode (kildetilstand); se nedenfor.
Hvad der tjekkes
Go: de binærfiler, du leverer
Når fremforge scanner container-images i din organisations registry igen, læses hver Go-binærfil med et sårbarhedsfund af govulncheck i binærtilstand. govulncheck læser binærfilens modulliste og symboltabel og sammenligner dem med Gos sårbarhedsdatabase, som navngiver præcis de funktioner, hver advisory berører.
- Intet i dit image bygges eller køres. Binærfilen læses som en fil.
- Ingen tjeneste kaldes. Sårbarhedsdatabasen er fremforges egen kopi af OSV’s Go-poster, opdateret dagligt.
- govulncheck (BSD-3-Clause) er fastlåst til en release og opdateres gennem Renovate.
Terraform- og OpenTofu-providers: de binærfiler, dine lockfiler fastlåser
Et fund i en Terraform- eller OpenTofu-provider er et Go-modul, der er bygget ind i den provider-binærfil, din .terraform.lock.hcl fastlåser. fremforge læser den binærfil med govulncheck i binærtilstand, som for en Go-binærfil i et image, og fundet får vurderingen kan nås, når en berørt funktion er linket ind i provideren, og ikke nåbar, når modulet (eller dets pakke) er i binærfilen, men ingen af de funktioner, advisoryen navngiver, er det.
- Provider-releases bygges uden symboltabel (
-ldflags=-s). Den funktionstabel, Go beholder til kørselstidspunktet, er der stadig; fremforge genskaber det ene symbol, govulncheck skal bruge for at læse den, og resultatet er det samme som for den samme provider bygget med sine symboler. Kan det symbol ikke findes, forbliver vurderingenunknown(no_symbol_table). - Hver providerversion analyseres én gang for alle organisationer, der fastlåser den, ud fra den kopi, fremforges provider-spejl gemmer. Intet om dit repository bruges.
- En provider-binærfil på over 512 MiB (for eksempel
hashicorp/aws) beholder vurderingenunknown(engine_failed).
Go: dit repositorys kode
Når en afhængighedsscanning finder sårbare Go-moduler, kører fremforge også govulncheck i kildetilstand på den scannede commit. Den typetjekker dine moduler og bygger en kaldgraf ud fra dine main-pakker, så den kan vise kaldstien fra en linje i dit repository til den berørte funktion, også når der ikke er bygget noget image fra den commit.
Det kræver go-kommandoen, som et repository kan forsøge at styre. fremforge kører den, så intet fra dit repository udføres, og intet hentes andet end gennem din organisations afhængighedsproxy. Designet blev gennemgået, før det blev udgivet.
- Intet i dit repository kører. Ingen
go generate, ingen tests, intet build, ingen cgo (CGO_ENABLED=0), ingen-toolexec. Kun Go-værktøjskædens egen typetjekker læser din kode. - Ingen anden værktøjskæde. En
toolchain-linje ignoreres (GOTOOLCHAIN=local). Engo-linje, der er nyere end fremforges Go, gør moduletunknown(build_failed). fremforge holder sin Go opdateret gennem Renovate. - Ingen versionsstyring og intet andet netværk. Moduler kommer kun fra din organisations afhængighedsproxy gennem et relæ, der tilføjer fremforges scanningslegitimation, så din pakkepolitik gælder. Der er ingen fallback til en versionsstyringsvært. Har din organisation slået sin afhængighedsproxy fra, læser scanningen i stedet moduler fra fremforges egen scanningscache på den samme proxy. Den cache indeholder kun offentlige moduler fra
proxy.golang.org, hver tjekket modsum.golang.org, og bruger ingen af dine legitimationsoplysninger, så din pakkepolitik gælder ikke for de læsninger. En organisation, hvis proxy afviser et modul efter sin politik, fårunknownfor det; scanningen går aldrig uden om din proxy. - Private moduler anmodes der aldrig om. Et modul under
frem.sh, eller som matcher etGOPRIVATE-,GONOPROXY- ellerGONOSUMDB-mønster, som dit repository angiver (i sine CI-workflows,go.env,.envrc,.envellerMakefile), afvises, før nogen request forlader scanningen. Dets sti sendes aldrig til afhængighedsproxyen, tilproxy.golang.orgeller tilsum.golang.org, og alt, der har brug for det, erunknown(build_failed). Samme regel gælder for opslag af licens, release-alder og afhængighedsgraf for Go. Se hvad der når Google for offentlige moduler. - Dine indstillingsfiler læses ikke. En committet
GOFLAGS-fil,go.enveller.config/go/env, envendor/-mappe og en.netrcignoreres. Symlinks følges ikke. - Afvist før analysen som
unknown(build_failed): et modul, der styres af engo.work(den ændrer, hvilken kode der bygges), enreplacetil en absolut sti eller uden for repositoriet og en modulsti, der direkte navngiver et versionsstyringsrepository (….git). - Adskilt fra fremforges legitimationsoplysninger. Analysen kører i sin egen container, der ikke har nogen legitimationsoplysninger og ikke kan nå andet end relæet. Den har sine egne grænser for hukommelse og CPU.
- Grænser: 20 moduler, 20.000 filer og 128 MiB af dit repository pr. scanning, 512 MiB moduldownloads og et tidsbudget på 3 minutter pr. scanning. Over en grænse giver
unknown. - Tests (
_test.go) analyseres ikke, ligesom i binærtilstand. Standardbiblioteket vurderes kun i binærtilstand: kildetilstand ville læse det i fremforges Go-version, ikke din. - Den får aldrig scanningen til at fejle og ændrer aldrig
fremforge/dep-scan-statussen.
JavaScript og TypeScript: dit repositorys kode
Når en afhængighedsscanning finder sårbare npm-pakker, kører fremforge Jelly, en statisk kaldgrafanalysator for JavaScript og TypeScript fra Aarhus Universitet, på den scannede commit. Den tjekker, om din kode indlæser den sårbare pakke, direkte eller gennem andre pakker.
Jelly læser din kode. Den kører den aldrig: intet installeres, ingen pakkekode kører, og intet installationsscript kører.
Pakkerne på vejen til en sårbar pakke hentes ud fra navn og version og pakkes ud som data. Hver af dem tjekkes mod integritetshashen i din lockfil, og dit repositorys
.npmrcbruges ikke. De kommer gennem din organisations afhængighedsproxy (se Hvor pakkefilerne kommer fra).Hver tarball læses som en strøm. Den tjekkes mod sin integritetshash, mens den ankommer, og kun de filer, Jelly læser, skrives:
.js,.mjs,.cjs,.jsx,.ts,.mts,.cts,.tsxog.json. Native binærfiler og andre store filer springes over uden at blive gemt, så en pakke somonnxruntime-node(108 MiB) analyseres som enhver anden. Filer gemmes kun, når hashen stemmer.Grænser: en tarball på op til 512 MiB, 2 GiB udpakket, 100.000 poster, 10.000 skrevne filer og 16 MiB pr. skrevet fil. Alle de pakker, der lægges ud for én lockfil, kan fylde op til 96 MiB skrevne filer. En pakke over en grænse gør de fund, der har brug for den,
unknown(build_failed). En fil, der springes over på grund af sin størrelse, lader aldrig et fund bliveunreachable.Understøttede lockfiler:
Lockfil Versioner Integritet tjekket mod package-lock.json,npm-shrinkwrap.jsonlockfilversion 2 eller 3 (npm 7 og nyere) lockfilen pnpm-lock.yaml5.x, 6 og 9 lockfilen yarn.lock, classicyarn 1 lockfilen ( integrityeller SHA-1 i en ældreresolved-URL)yarn.lock, berryyarn 2 og nyere ( __metadataversion 4 og nyere)den integritet, dit registry offentliggør for den version, fordi berrys checksumdækker yarns eget cachearkiv og ikke npm-tarballen. En pakke, hvis offentliggjorte integritet ikke kan læses, hentes ikke.bun.locktekstformat (bun 1.2 og nyere) lockfilen For yarn classic, som ikke registrerer workspaces, læses også
package.jsonved siden af lockfilen og densworkspaces.bun.lockb, buns ældre binære format, læses ikke: det er et udokumenteret hukommelsesbillede, der har ændret sig mellem bun-versioner. Dets fund erunknown, og beviserne siger hvorfor. Andre lockfiler giverunknown.Jelly (BSD-3-Clause) kører inde i fremforges scanningsjob og kalder ingen tjeneste. Den er fastlåst til en release og opdateres gennem Renovate.
Analysen har et tidsbudget på 2 minutter pr. scanning. Den får aldrig scanningen til at fejle. Den ændrer kun
fremforge/dep-scan-statussen, hvis din organisation har valgt ikke at blokere på fund, der ikke er nåbare.
Python, Java og Kotlin: dit repositorys imports
Når en afhængighedsscanning finder sårbare PyPI- eller Maven-pakker, tjekker fremforge, om din kode importerer dem. Det er kun på importniveau: det fortæller dig, at en pakke indlæses, aldrig at den sårbare kode kører, og det giver aldrig unreachable.
Python. Dine
.py-filer parses med Pythons egetast-modul, som kun parser. Intet importeres eller køres. fremforge læserimport- ogfrom … import-sætninger samt kald afimportlib.import_module(...)og__import__(...)med et bogstaveligt navn. En fil, der ikke kan parses med nuværende Python, for eksempel Python 2-kode, læses i stedet linje for linje efter dens import-sætninger. Relative imports (from . import x) er dine egne moduler og springes over, ligesom virtuelle miljøer (.venv,venv,site-packages) og symlinks.Python, gennem andre pakker. Når din kode ikke selv importerer en sårbar pakke, følger fremforge de pakker, din kode importerer: den læser deres kode fra deres wheels på samme måde, startende ved de moduler, din kode importerer, og følger kun deres egne imports. Importerer kode, der nås på den måde, den sårbare pakke, er fundet Importeret, og dets beviser viser stien: din import og derefter importen inde i hver pakke, for eksempel
idnagennemrequests. Et modul, som intet indlæser (som en pakkeshelp.py), og imports underif TYPE_CHECKING:følges ikke. Denne gennemgang går højst tre pakker i dybden og læser højst 40 wheels på op til 16 MiB hver pr. scanning. Den tilføjer kun vurderinger af typen Importeret; en sti, den ikke kan følge, efterlader fundetunknown.Java, Kotlin, Groovy og Scala. fremforge læser
import-sætninger, fuldt kvalificerede klassenavne i koden samtClass.forName("…")ogloadClass("…")med et bogstaveligt navn. Kommentarer og strengliteraler ignoreres, og det gørbuild/ogtarget/også. Intet kompileres.Java og Kotlin, gennem andre pakker. Når din kode ikke selv importerer en sårbar Maven-pakke, følger fremforge de pakker, din kode importerer, i deres kompilerede klasser. Den starter ved de klasser, din kode importerer (hver klasse i pakken ved en wildcard-
import a.b.*). Derfra følger den de klasser, de bruger: hver klasse, en metode kalder, opretter, caster til eller læser et felt fra, og hver superklasse og hvert interface. De læses fra hver klassefils konstantpulje. Bruger en klasse, der nås på den måde, en klasse fra den sårbare pakke, er fundet Importeret. Dets beviser viser stien: din import og derefter kildefilen og linjen inde i hver pakke, hvor den næste bruges. Et eksempel ercommons-textgennemcommons-configuration2. En klasse, som intet når, følges ikke, og det gør en klasse, der indlæses ved navn fra en streng, heller ikke. Klassefiler læses som data: ingen klasse indlæses eller køres, og ingen JVM er involveret. Denne gennemgang går højst tre pakker i dybden og læser højst 40 JAR-filer på op til 32 MiB hver pr. scanning, én ad gangen. Den tilføjer kun vurderinger af typen Importeret; en sti, den ikke kan følge, efterlader fundetunknown.Hvilke navne en pakke stiller til rådighed, kommer fra fillisten i dens offentliggjorte arkiv, læst som data:
- PyPI: wheelen for den version. En namespace-pakke opløses til sin første rigtige pakke, for eksempel
google.protobufforprotobuf. - PyPI, en release uden wheel (kun sdist): kildearkivet, læst som data og aldrig installeret.
setup.pybliver hverken kørt eller læst. Navnene kommer fra pakkelisterne isetup.cfgellerpyproject.toml(setuptools, hatch, flit og poetry) eller ellers fra de mapper, der indeholder en__init__.py, øverst, undersrc/eller under en mappe somlib/. Såpysaml2stillersaml2til rådighed, ogpycryptostillerCryptotil rådighed.PKG-INFOskal navngive det samme projekt. Arkiver på op til 16 MiB læses (.tar.gz,.tar,.zip). En release, der ikke findes på noget index, eller en sdist, der ikke navngiver noget (for eksempel en.tar.bz2), falder tilbage til projektnavnet, sårequestsstår forimport requests; bevisernesmappingsiger det. - Maven: JAR-filen på Maven Central og de Java-pakker, dens klasser ligger i.
For en wheel eller JAR hentes kun arkivets indholdsfortegnelse med HTTP range-requests, så en stor fil koster få kilobytes. Gennemgangen gennem andre pakker læser hele wheelen eller JAR-filen for hver pakke, den følger, og en sdist læses altid hel. Intet installeres, bygges eller køres.
- PyPI: wheelen for den version. En namespace-pakke opløses til sin første rigtige pakke, for eksempel
Dit repository bygges ikke. Nåbarhed for Java med kaldgrafer, som osv-scanners eksperimentelle JAR-analyse eller
jdeps, kræver en bygget JAR. En scanning af en pull request bygger ikke dit projekt, så de værktøjer bruges ikke.Analysen har et tidsbudget på 1 minut pr. økosystem pr. scanning og kører side om side med npm-analysen. Den får aldrig scanningen til at fejle og ændrer aldrig
fremforge/dep-scan-statussen.
Hvor pakkefilerne kommer fra
npm-tarballs, PyPI-indekser og wheels samt Maven-JAR-filer læses gennem din organisations afhængighedsproxy ad en intern rute, som kun fremforges scanningstjeneste kan nå. Så din organisations pakkepolitik, cache, lagerloft og upstream-rate gælder for dem som for enhver anden hentning, og det, scanningen henter, caches til dine builds.
- Afviser din politik en pakke (for eksempel malware, en for ny release eller en licensregel), henter scanningen den ikke andre steder fra. De fund, der har brug for den, er
unknown(build_failed), og beviserne navngiver proxyens afgørelse. - Har din organisation slået afhængighedsproxyen fra, eller kan proxyen ikke svare, læses filerne i stedet fra de offentlige registries (npmjs, PyPI, Maven Central) som før.
- Filer, scanningen henter, tæller med i din organisations proxylager som enhver anden cachet fil.
Niveauerne
En vurdering har et niveau: hvor meget motoren kunne se.
| Niveau | Betydning |
|---|---|
function | Advisoryen navngiver de berørte funktioner, og motoren ledte efter en sti til dem. Det er det, govulncheck giver for Go. |
import | Advisoryen navngiver ingen berørte funktioner. Motoren kan kun sige, om den sårbare pakke indlæses. |
npm-advisories navngiver næsten aldrig berørte funktioner. Da det blev målt den 12.10.2026, gjorde ingen af de 230.287 npm-poster i OSV-databasen det. Derfor er vurderinger for JavaScript og TypeScript på importniveau: de fortæller dig, at din kode indlæser den sårbare pakke, ikke at den kalder den sårbare kode. Navngiver en npm-advisory berørte funktioner, tjekker Jelly dem på funktionsniveau.
Vurderinger for Python og Maven er altid på importniveau. Den samme måling fandt data om berørte funktioner i 2 af 26.221 PyPI-poster og i ingen af de 7.190 Maven-poster.
De tre vurderinger
Hvert fund i afhængigheder og images har en af disse:
| Vurdering | Go (govulncheck) | JavaScript og TypeScript (Jelly) | Python, Java og Kotlin (importniveau) |
|---|---|---|---|
| Kan nås | En berørt funktion er linket ind i binærfilen. Go-linkeren udelader kode, som intet kan kalde, så en linket funktion er en, dit program kan nå. Markøren navngiver funktionen, for eksempel html.Renderer.renderLink. I kildetilstand: en kaldsti fra din kode når en berørt funktion; markøren angiver filen og linjen for det sidste kald i dit repository, før stien går ind i afhængigheden, for eksempel din handler i stedet for main. Hele stien står i beviserne. | Importniveau, vist som Importeret: din kode indlæser pakken i den sårbare version, direkte eller gennem andre pakker. Funktionsniveau, vist som Kan nås: et kald i din kode kan nå en berørt funktion. Markøren angiver filen og linjen i dit repository, for eksempel src/session.ts:12. | Vist som Importeret: din kode importerer et modul eller en Java-pakke, som den sårbare pakke stiller til rådighed. Markøren angiver filen og linjen for importen, for eksempel app/main.py:2. |
Ikke nåbar (unreachable) | Modulet er i binærfilen i en berørt version, advisoryen navngiver de berørte funktioner, govulncheck kørte færdig, og ingen af de funktioner er i binærfilen. I kildetilstand: modulet bruges i en berørt version, govulncheck fandt ingen kaldsti til nogen berørt funktion, og intet, som govulncheck ikke kan følge (reflection, filer til andre platforme, cgo, plugins), er i din kode. | Advisoryen navngiver de berørte funktioner, Jelly kørte færdig med alle pakker på vejen tilgængelige, og intet kald i din kode når en af dem. Uden de funktionsdata er en pakke, din kode aldrig indlæser, unknown, ikke unreachable. | Aldrig. Imports inde i andre pakker følges kun, så vidt de navngiver et modul eller en klasse bogstaveligt, så en pakke, din kode ikke ser ud til at indlæse, kan alligevel blive indlæst. |
| Ukendt | Alt andet. Det er standarden, og det behandles aldrig som sikkert. | Det samme. | Det samme, inklusive alle pakker, din kode ikke importerer. |
unreachable kræver alle sine betingelser. Et manglende input giver altid unknown med årsagen:
| Årsag | Hvorfor |
|---|---|
no_symbol_data | Advisoryen navngiver ikke de berørte funktioner, så fraværet af en sti beviser intet. For npm er det den sædvanlige årsag, når din kode ikke indlæser pakken. For Python og Maven er det årsagen, når din kode ikke importerer pakken. |
no_symbol_table | Go: binærfilen blev bygget med -ldflags=-s. Dens symboler kan ikke læses, så ingen af vurderingerne kan gives. Byg uden -s (det er fint at beholde -w) for at få vurderinger. Terraform-providers: det symbol, fremforge genskaber, kunne ikke findes i denne binærfil. |
build_failed | Go-kildetilstand: modulet blev afvist før analysen (se ovenfor), kunne ikke indlæses, eller et modul kunne ikke hentes fra din afhængighedsproxy. npm: lockfilen er ikke et af de understøttede formater, eller en pakke på vejen kunne ikke hentes, var over en grænse eller matchede ikke sin integritetshash. Python og Maven: wheelen, sdisten eller JAR-filen kunne ikke læses, for eksempel et artefakt, der kun er en POM, eller et, der ikke er på Maven Central. |
dynamic_code | Din kode indlæser moduler eller klasser ud fra beregnede navne, så en manglende kaldsti eller import beviser intet. npm: require(name) og import(name). Python: importlib.import_module(name) og __import__(name). Java: Class.forName(name) og loadClass(name). Go-kildetilstand: plugin-pakken eller //go:linkname. |
reflection | Go-kildetilstand: din kode kalder metoder gennem reflect (MethodByName, Method, Call) eller bruger text/template eller html/template, når advisoryen navngiver metoder. govulncheck kan ikke følge de kald, så en manglende kaldsti beviser intet. |
build_constraints | Go-kildetilstand: en fil, som analysen ikke indlæste, importerer andre pakker. Analysen indlæser din kode som til Linux på amd64 uden cgo, så en _windows.go-fil, en fil, hvis //go:build-linje udelukker Linux, eller en cgo-fil er ikke i kaldgrafen, og et kald, der kun foretages dér, ville blive overset. En pakke, der kun bygger med cgo (for eksempel en desktop-UI på et værktøjssæt, der kun findes med cgo), udelades af analysen i stedet for at få den til at fejle: resten af modulet analyseres, og hvert modul, pakken importerer, får denne årsag i stedet for unreachable. |
timeout | Analysen overskred sit tidsbudget (5 minutter pr. image for Go, 2 minutter pr. scanning for npm, 1 minut pr. økosystem pr. scanning for Python og Maven). |
engine_no_match | Go: govulncheck rapporterede ikke denne modulversion som berørt af advisoryen, selvom image-scanneren gjorde. Ingen af dem stoles mere på end den anden. |
oom_killed | Go-kildetilstand: analysen løb tør for hukommelse og blev stoppet, så intet blev afgjort. |
engine_failed | Analysen kunne ikke køre på denne binærfil eller dette repository. |
not_analysed | Der er ikke beregnet nogen vurdering: fundet er ikke blevet scannet, siden nåbarhed blev tilføjet, eller et Go-fund har intet image bygget fra sin commit. |
unsupported_ecosystem | Et afhængighedsfund uden for Go, npm, PyPI, Maven og Terraform-providers, for eksempel NuGet eller Cargo. |
Fund i afhængigheder
Go. Et Go-afhængighedsfund får sin vurdering i binærtilstand fra et image, der er bygget fra præcis den commit. Hvor kildetilstand er slået til (indtil videre fremforges interne organisationer), får det også en ved hver scanning, med kaldstien i dit repository. Mærk dine images med de to standard-OCI-labels:
org.opencontainers.image.source=https://frem.sh/<org>/<repo>
org.opencontainers.image.revision=<full commit sha>docker/metadata-action sætter begge. Vurderingen gælder kun den commit, imaget navngiver, og de modulversioner, binærfilerne blev bygget med. Kunne en Go-binærfil i det image ikke læses, forbliver afhængighedsfundet unknown. Indeholder flere binærfiler modulet, kan fundet nås, når en af dem når det.
Når begge tilstande vurderer det samme fund på den samme commit, sletter ingen af dem den anden: en unknown fra den ene erstatter aldrig en vurdering fra den anden, og ikke nåbar fra den ene erstatter aldrig kan nås fra den anden. Beviser fra kildetilstand har "mode": "source".
npm, PyPI og Maven. Vurderinger kommer med selve afhængighedsscanningen: hver scanning af en pull request og scanningen af din standardbranch efter hvert push (højst en gang i timen). En vurdering hører altid til den commit, der blev scannet. Optræder den samme pakke og advisory i flere lockfiler, kan fundet nås, når en af dem når det.
Sådan bruger fremforge det
Rangering. Listerne over fund under Afhængigheder og Container-images er sorteret med dem, der kan nås, først, så ukendte og til sidst dem, der ikke er nåbare. Inden for hver gruppe er de sorteret efter alvorlighed, så kendt udnyttede før resten og så efter EPSS. Et fund er kendt udnyttet, når et af dets CVE-id’er, dets egne eller advisoryens aliasser, er opført som udnyttet i ENISA’s EU Vulnerability Database eller i CISA’s Known Exploited Vulnerabilities-katalog. Begge lister viser mærket Kendt udnyttet, hvis tooltip navngiver kilden: EU (ENISA EUVD), US (CISA KEV) eller begge, og over hver liste viser Kun kendt udnyttede netop de fund (fund-API’ets ?known_exploited=true). Begge lister opdateres dagligt. Et fund markeret Importeret rangeres sammen med dem, der kan nås. Samme rækkefølge bruges af:
- fanen Anbefalinger, hvor et kort (én opgradering af én pakke i ét repository) tager den mest nåbare vurdering blandt de fund, det retter, og markeres Kan nås eller Ikke nåbar;
- det ugentlige sammendrags Top fixable today, som viser hver rækkes vurdering;
- fund-API’et med
?sort=risk.
Varsler. Når et åbent afhængighedsfund bliver nåbart eller kendt udnyttet, får din SIEM straks en revisionshændelse, og organisationens sikkerhedskontakter får en e-mail, én gang pr. fund: se Sikkerhedsvarsler. Kendt udnyttede og nåbare med alvorligheden HIGH eller CRITICAL mailes med det samme. Nåbare med alvorligheden MEDIUM eller LOW kommer med i hver persons daglige oversigt over varsler, eller med det samme for den, der har slået oversigten fra. Opsætningstjeklisten under Sikkerhed › Overblik viser, hvilke af dine images der har Go-binærfiler uden symboler.
Gruppen af sandsynligvis ikke udnyttelige. Fund, der ikke er nåbare, flyttes til en sammenklappet gruppe nederst i listen med antallet i titlen. De forbliver synlige, kan vælges og afvises, og de tælles med i alle totaler.
Intet skjules eller afvises. En vurdering skriver aldrig en afvisning. Den ændrer kun et funds SLA, når din organisation har valgt SLA-multiplikatoren. Som standard læser commit-statussen (fremforge/dep-scan, fremforge/image-scan) ikke vurderinger: det, der blokerer en merge eller en hentning, er uændret. Den ene undtagelse er den valgfri politik om ikke at blokere pull requests på fund, der ikke er nåbare, som kun gælder for fremforge/dep-scan.
SLA-multiplikator (valgfri)
En ejer af organisationen kan forlænge alvorligheds-SLA’en for fund, der ikke er nåbare, under Sikkerhed › Prioritér › Rettefrist (SLA) (/<org>/_admin/security/prioritise/sla) eller med unreachable_sla_multiplier på PUT /orgs/{org}/security/sla-policy. Værdien er et helt tal fra 1 til 4. Standarden, 1, er slået fra.
- Kun fund, der er
unreachable, forlænges. Fund, der kan nås, og ukendte fund beholder altid den fulde SLA, og det gør et fund, der ikke er analyseret, også. - Et kendt udnyttet fund (opført af EU (ENISA EUVD) eller US (CISA KEV), se Rangering ovenfor) forlænges aldrig, uanset alvorlighed og vurdering.
- Et kritisk fund, hvis EPSS-score er i top 10 % (percentil 0,90 eller derover), forlænges aldrig, uanset vurdering.
- Fristen regnes altid fra, da fundet først blev set. Når en senere scanning finder en kaldsti eller ikke kan afgøre det, gælder den fulde SLA straks igen, så fundet kan gå direkte til overskredet SLA. SLA-mærket siger så hvorfor.
- Med multiplikatoren slået til viser et forlænget SLA-mærke et lille
×2(eller×3,×4) og et tooltip med begge frister. Det ugentlige sammendrags antal fund over SLA, overbliksfeltet og SIEM-hændelsencode-security.sla.breachedbruger de samme forlængede frister. - Multiplikatoren ændrer kun frister. Den ændrer ikke, hvad der blokerer en pull request, og den skjuler intet.
Hver ændring revideres som code-security.sla_policy.updated med den tidligere værdi.
Blokér ikke på fund, der ikke er nåbare (valgfri)
Som standard blokerer hvert afhængighedsfund på eller over din blokeringstærskel pull requesten, uanset vurdering. En ejer af organisationen kan vælge, at et fund, der ikke er nåbart, ikke blokerer fremforge/dep-scan. Det er slået fra, medmindre du slår det til.
Slå det til under Sikkerhed › Prioritér › Pull request-tjek (/<org>/_admin/security/prioritise/pr-checks) eller med PUT /orgs/{org}/security/dep-scan-unreachable-policy (se API). Du kan begrænse det til en liste af repositorier; en tom liste betyder alle repositorier i organisationen.
Hvad det ændrer, og hvad det aldrig ændrer:
- Kun
unreachablemed beviser kvalificerer. Fundets vurdering for pull requestens head-commit skal være ikke nåbar, beregnet af en motor med dens version og de berørte funktioner fra advisoryen, som den tjekkede. I dag betyder det Go samt JavaScript og TypeScript. For Go giver govulncheck vurderingen i binærtilstand, når et image bygget fra pull requestens head-commit er blevet scannet; en vurdering, der ankommer efter scanningen, gælder fra pull requestens næste scanning. Hvor kildetilstand er slået til (indtil videre fremforges interne organisationer), giver den også en ved selve scanningen af pull requesten. For JavaScript og TypeScript giver Jelly den, når advisoryen navngiver berørte funktioner. Vurderinger for Python, Java og Kotlin er på importniveau og er aldrigunreachable, så de blokerer altid. unknownblokerer altid. Der er ingen mulighed for ikke at blokere påunknown, og et fund, der ikke er analyseret, erunknown.- Malware og kendt udnyttede sårbarheder blokerer altid, uanset vurdering: en
MAL--advisory eller en advisory markeret som ondsindet, og en sårbarhed, hvor et af dens CVE-id’er er opført som udnyttet af EU (ENISA EUVD) eller US (CISA KEV). Kan fremforge ikke læse disse oplysninger under en scanning, slippes intet igennem ved den scanning. - Intet skjules. Fundet gemmes, vises, tælles med i alle totaler og giver varsler som ethvert andet. Det afvises ikke, og dets SLA er uændret (medmindre SLA-multiplikatoren også er slået til).
- Kun pull requests. Scanningen af din standardbranch registreres nøjagtigt som før.
- Træf på afvisningslisten og blokeringstærsklen er uændrede. Et fund under tærsklen blokerede aldrig, og en afvist komponent blokerer stadig.
Blokeringen vender tilbage. Når en senere scanning af pull requesten finder en kaldsti eller ikke kan afgøre det, blokerer fundet igen. En vurdering, der beregnes uden for en scanning (govulncheck på et image), og at politikken slås fra eller indsnævres, opfanges inden for en time: fremforge tjekker igen hver pull request, der passerede på grund af politikken, og genberegner dens status, kommentar og revisionshændelse. Det samme sker, når et fund bliver kendt udnyttet.
Hvad pull requesten viser. fremforge/dep-scan-statussen siger, hvor mange fund der ikke blokerede, for eksempel 2 finding(s); 1 at or above critical with no call path, not blocking (org policy). Kommentaren markerer hvert sådant fund not blocking og viser dem under Not blocking: no call path (org policy) med motoren, dens version, sårbarhedsdatabasens dato og de funktioner, den tjekkede. Et fund uden kaldsti, der alligevel blokerer, vises under Blocking although no call path was found med årsagen (malware eller kendt udnyttet).
Revision. Hver ændring af politikken revideres som code-security.deps.unreachable_policy.updated med den nye og den tidligere værdi, om den ændrede sig, og om den kom fra konsollen eller API’et. Hver scanning af en pull request, mens politikken gælder, registrerer i sin code-security.dep_scan.ingest-hændelse hvert fund, der ikke blokerede (unreachable_not_blocking, med den motor, version og databasedato, der blev lagt til grund), og hvert, der alligevel blokerede (unreachable_blocked_anyway, med why). Et gentjek har trigger: unreachable_policy_recheck og årsagen. Begge når dine SIEM-endpoints.
Når en vurdering ændrer sig: reachability_changed
En afvisning eller en undtagelse kan bygge på en vurdering. Når du afviser et fund i en afhængighed eller et image, hvis vurdering er ikke nåbar, eller beder om en undtagelse for det, registrerer fremforge den vurdering, den byggede på: motoren, dens version, databasedatoen og den commit eller det image, den blev beregnet på. Afvisningspanelet siger det.
Hver time tjekker fremforge de afvisninger og undtagelser. Når en scanning efter afvisningen finder det samme fund reachable eller ikke kan afgøre det (unknown):
- tilbagekaldes en undtagelse med årsagen
reachability_changed; - tilbagekaldes en almindelig afvisning: fundet åbnes igen, og en afvisning for hele repositoriet, som den lavede, holder op med at gælde for senere scanninger;
- giver fundet varsel igen gennem det samme sikkerhedsvarsel som en udløbet afvisning;
- er begge revisionshændelser (
code-security.exception.revoked, ellercode-security.deps.dismissal_revokedogcode-security.images.dismissal_revoked) med den vurdering, der blev lagt til grund, og den nye, og de når dine SIEM-endpoints. Fundhændelsen siger det også:security.finding.exception_revoked, eller for en almindelig afvisningsecurity.finding.dismissal_revoked, begge medtransition_reasonreachability_changed.
Et fund, der ikke er analyseret igen, beholder sin afvisning: fraværet af en ny scanning er ikke en ny vurdering. En afvisning, der blev lavet, mens vurderingen ikke var unreachable, registrerer intet og tilbagekaldes aldrig af dette tjek, og afvisninger fra før dette blev tilføjet, tjekkes ikke. Har du afvist et fund af en grund, der ikke afhænger af nåbarhed, så afvis det igen efter tilbagekaldelsen; vurderingen er da ikke længere unreachable, så den nye afvisning bliver stående.
Triagesignaler for SAST
SAST-fund har ingen kaldgraf, så i stedet rangerer tre deterministiske signaler dem. Ingen AI-model er involveret.
| Signal | Hvad det er |
|---|---|
| Placering | Ud fra filstien: testkode (test/, __tests__/, *.test.ts, *_test.go, test_*.py, *Test.java og lignende), eksempler og dokumentation, tredjepartskode (vendor/, third_party/, node_modules/) og genereret kode (*.pb.go, *.min.js, gen/, zz_generated* og lignende). |
| Taint-sti | OpenGreps regler i taint-tilstand sporer data fra en kilde, som brugerinput, til et sink. Et match med et spor markeres Taint-sti og rangeres over et match, der kun bygger på et mønster. Kun kendsgerningen gemmes, aldrig sporet. |
| Ofte afvist her | Folk afviste den samme regel på mindst 2 andre fund i dette repository, eller 5 i organisationen, inden for de seneste 90 dage. Bots, automatisk løsning og andre systemaktører tæller ikke. |
Et fund i test-, eksempel-, tredjeparts- eller genereret kode, eller et, der er markeret ofte afvist her, flyttes til en sammenklappet gruppe, Lavere troværdighed, nederst i SAST-listen med antallet i titlen. En taint-sti flytter ikke et fund ud af den gruppe: et taint-match i en testfil er stadig i en testfil. Inden for hver gruppe sorteres fund efter alvorlighed, så taint-sti og så alder, ældste først.
Ligesom gruppen af sandsynligvis ikke udnyttelige bliver fund med lavere troværdighed aldrig skjult eller afvist: de beholder deres fulde SLA, tælles med overalt og kan vælges, rettes og afvises som alle andre. SAST-fund-API’et returnerer signalerne som et triage-objekt på hvert fund, og ?sort=risk viser fund i denne rækkefølge på tværs af sider.
Kommentar på pull requesten. Kommentaren fra afhængighedsscanningen sorterer fund på samme måde og markerer hvert med sin vurdering, når der findes en for pull requestens commit: reachable med funktionen eller filen og linjen, imported med filen og linjen (npm, Python, Java og Kotlin) eller no call path. Med politikken om ikke at blokere på fund, der ikke er nåbare, slået til viser den også, hvilke fund der ikke blokerede og hvorfor.
Måling af dækning
Andelen af dine åbne afhængighedsfund med en vurdering og andelen, der ikke er nåbar, pr. økosystem og over 30 eller 90 dage, står på siden Udbedringsmålinger.
Hvad statisk analyse ikke kan se
En manglende kaldsti er et stærkt indicium, ikke et bevis. Ingen af motorerne ser kode, der nås gennem reflection, plugins, unsafe, eval, dependency injection eller genereret kode, eller kode uden for det analyserede: en separat CLI, et delt bibliotek eller for Go alt uden for binærfilen. En advisory kan også navngive de forkerte funktioner.
For Go-kildetilstand dækker kaldgrafen dine main-pakker og eksporterede funktioner som bygget til Linux på amd64 uden cgo. Kald gennem interfaceværdier og funktionsværdier følges. Kald gennem reflection og kald, der kun findes i filer til andre platforme eller i cgo-filer, følges ikke, og derfor er de fund unknown (reflection, build_constraints) i stedet for ikke nåbar.
For JavaScript og TypeScript er kaldgrafen omtrentlig. Jelly er en analysator af forskningskvalitet, og en dynamisk require eller import() forhindrer enhver unreachable-vurdering for repositoriet. En vurdering af typen Importeret siger, at pakken indlæses. Den siger ikke, at den sårbare kode kører.
For Python og for Java og Kotlin følges imports gennem andre pakker (se ovenfor). For Python virker det kun, så vidt deres kode navngiver et modul bogstaveligt. For Java og Kotlin virker det kun, så vidt deres kompilerede klasser navngiver en klasse. En pakke, der indlæser moduler eller klasser ud fra beregnede navne, ServiceLoader eller reflection, følges ikke længere end dertil. Frameworks, der indlæser klasser fra konfiguration, som JDBC-drivere og dependency injection, ses heller ikke. En Java- eller Kotlin-pakke, der kun bruges på den måde, vises som unknown, selvom den indlæses.
Derfor hedder gruppen sandsynligvis ikke udnyttelige, og derfor viser hver vurdering motoren, dens version og databasedatoen: tjek beviserne, før du afviser et fund.
API
Hvert fund fra GET /orgs/{org}/code-security/deps/findings og GET /orgs/{org}/code-security/images/findings har et reachability-objekt. For en Go-binærfil:
"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"
}For Go-kildetilstand går rammerne fra dit repositorys indgangspunkt til den berørte funktion gennem standardbiblioteket og din egen handler (en plantet test, 13.10.2026):
"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"
}En ramme uden package er i dit repository med en file relativt til repositoriet. En ramme med package er i en afhængighed eller standardbiblioteket, og dens file er relativ til det modul. Højst 8 rammer beholdes: indgangspunktet og derefter de sidste 7 ned til den berørte funktion (eksemplet ovenfor udelader 3 rammer fra standardbiblioteket).
For en npm-pakke, din kode indlæser gennem en anden pakke:
"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"
}For en Python-pakke, din kode importerer:
"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"
}For en Python-pakke, der kun indlæses gennem en anden pakke, er frames stien, som for npm, og via navngiver pakkerne på den:
"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" }
]
}Vurderinger for Maven har samme form, med engine jvm-imports, mapping, der navngiver JAR-filen, og provides, der viser dens Java-pakker. Gennem en anden pakke navngiver en ramme inde i en JAR kildefilen fra klassens debuginformation og linjen, hvor den næste pakkes klasse bruges. Linjen er 0, når ingen instruktion bruger den, som for et implementeret 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" }
]
}For en Python-release, der kun findes som sdist, navngiver mapping sdisten, og hvordan navnene blev fundet, for eksempel sdist pysaml2-4.4.0.tar.gz, package directories under src/.
Den første npm-ramme er linjen i dit repository. Rammerne efter den er filer og linjer inde i pakkerne på vejen, hver navngivet med sin version.
Et fund i en pull request har også block_waived: "unreachable", når politikken om ikke at blokere på fund, der ikke er nåbare, lod det passere fremforge/dep-scan ved den seneste scanning, ellers null. Det er ikke en afvisning.
Selve politikken læses i dep_scan_unreachable_policy på GET /orgs/{org}/security og sættes med PUT /orgs/{org}/security/dep-scan-unreachable-policy (scope policy:write):
{ "enabled": true, "repos": ["web", "acme/api"] }enabled er påkrævet. repos tager navne på din organisations repositorier, uden præfiks eller som org/name; udelad den, eller send [], for alle repositorier. Svaret indeholder den gemte politik, den tidligere og om den ændrede sig.
Tilføj ?reachability=reachable, unreachable eller unknown for kun at vise dem. De tre værdier deler listen op uden overlap. Uden parameteren returneres alle fund. Beviser indeholder kun placeringer i koden, aldrig kodens indhold.
Tilføj ?sort=risk for at vise fund i triagerækkefølge: vurdering (kan nås, så ukendt eller ikke analyseret, så ikke nåbar), så alvorlighed, så kendt udnyttet (fund i afhængigheder og images), så EPSS for fund i afhængigheder og så de ældste først. Sideinddeling med offset er stabil i denne rækkefølge. Uden den, eller med sort=created, vises fund med de nyeste først som før.
Hvert SAST-fund fra GET /orgs/{org}/code-security/sast/findings har sine triagesignaler:
"triage": {
"confidence": "lower",
"reasons": ["test"],
"location": "test",
"dataflow": true,
"dismissed_before": { "repo": 0, "org": 1, "days": 90 }
}dataflow er true for et taint-match, false for et match, der kun bygger på et mønster, og null for et fund, der blev oprettet, før signalet fandtes. Den næste scanning af repositoriet udfylder det.