123% flere rapporterte CVE-er per dag i 2026 enn i fjor.

Avhengigheter

Hva er en transitiv avhengighet?

En transitiv avhengighet er en pakke programvaren din bruker fordi en annen pakke trenger den. Du har aldri deklarert den, men den er med i det du leverer, med egne sårbarheter og egen lisens. Her ser du hvordan du finner dem, retter dem og beviser hvilke som gikk inn i hver utgivelse.

Oppdatert

A vulnerable transitive dependency and its fix path An app declares two direct dependencies, express and hbs. Express brings in body-parser and send, which bring in raw-body and mime-types. Hbs brings in handlebars, which is vulnerable. The path from the app through hbs to handlebars is highlighted: upgrade hbs, or override the handlebars version. your project direct transitive, depth 1 depth 2 my-app express hbs body-parser send handlebars vulnerable, required by hbs raw-body mime-types Fix path: upgrade hbs, or override the handlebars version

Direkte og transitive avhengigheter

En direkte avhengighet er en du deklarerer i manifestet ditt. En transitiv avhengighet er en som avhengighetene dine deklarerer, og deres igjen, så dypt som treet går. Pakkebehandleren løser hele treet når den installerer, og registrerer vanligvis resultatet i en lockfile.

Ta en app som deklarerer én pakke, express. Kjører du npm ls --all, ser du hva den ene linjen tar med seg:

my-app
└─┬ express            ← direkte: du deklarerte den
  ├─┬ body-parser      ← transitiv, dybde 1
  │ └── raw-body       ← transitiv, dybde 2
  ├── cookie           ← transitiv, dybde 1
  └─┬ send             ← transitiv, dybde 1
    └── mime-types     ← transitiv, dybde 2

Det virkelige treet er lengre. De fleste pakkene i en typisk applikasjon kommer inn på denne måten, og det betyr at det meste av koden du leverer, ble valgt av pakkebehandleren, ikke av deg.

Direkte avhengighet Transitiv avhengighet
Hvem valgte den Teamet ditt, i manifestet Pakkebehandleren, ut fra manifestene til avhengighetene dine
Hvor den er oppført Manifest og lockfile Lockfile, hvis det finnes en
Hvem styrer versjonen Du Versjonsområdet til foreldrepakken, med mindre du overstyrer det
Slik retter du en sårbarhet Oppgrader den Oppgrader forelderen, eller overstyr versjonen

Hvorfor transitive avhengigheter er viktige

De har de samme risikoene som direkte avhengigheter, med mindre innsyn og mindre kontroll.

  • Sårbarheter. Da Log4Shell, en zero-day i log4j, ble offentliggjort, fant teamet bak Googles Open Source Insights 35 863 Maven Central-artefakter som var avhengige av den berørte log4j-koden. Omtrent 7 000 var direkte avhengige av den. Flertallet hentet den inn som en transitiv avhengighet, og mange kunne ikke rettes før en pakke imellom hadde levert en retting.
  • Leverandørkjedeangrep. Bakdøren i xz utils (CVE-2024-3094) nådde OpenSSH uten at OpenSSH var avhengig av xz. Flere Linux-distribusjoner patcher OpenSSH for å støtte systemd-varsling, og libsystemd er avhengig av liblzma, biblioteket xz leverer.
  • Lisenser. Hver transitiv pakke har sin egen lisens. En copyleft-lisens tre nivåer ned er like bindende som en du la til selv.
  • Inkompatible endringer. En foreldrepakke som godtar et versjonsområde, slipper inn en ny transitiv utgivelse ved neste nye installasjon, selv når ingenting i manifestet ditt er endret.

Slik lister du opp de transitive avhengighetene dine

Alle de store pakkebehandlerne kan skrive ut det oppløste treet:

Økosystem Kommando
npmnpm ls --all
pnpmpnpm list --depth Infinity
Python (uv)uv tree
Python (pip)pipdeptree
Gogo mod graph
Rustcargo tree
Mavenmvn dependency:tree
Gradlegradle dependencies

For å finne ut hvorfor en enkelt pakke er der, kan du be om stien til den: npm explain <package>, pnpm why, yarn why eller cargo tree -i <crate>. Vil du jobbe med stiene i stedet for å skrive dem ut, se avhengighetsgrafer.

Slik retter du en sårbar transitiv avhengighet

  1. Oppgrader forelderen. Finn den direkte avhengigheten som trekker inn pakken, og gå over til en utgivelse som krever en rettet versjon. Dette er den ryddigste rettingen, fordi vedlikeholderne av forelderen har testet den.
  2. Oppdater lockfilen. Hvis versjonsområdet til forelderen allerede tillater den rettede versjonen, er det nok å oppdatere oppføringen i lockfilen, for eksempel med cargo update -p <crate> eller en ny npm update.
  3. Overstyr versjonen. Hvis forelderen ikke har levert en retting, tvinger du versjonen selv: overrides i npm og pnpm, resolutions i Yarn, en constraints-fil med pip eller et høyere krav i go.mod. Test det, for forelderen ble aldri utgitt mot den versjonen.
  4. Bytt ut eller fjern forelderen. Hvis ingen av delene fungerer, er avhengigheten som bringer inn pakken, kanskje ikke lenger verdt å beholde.

Noen verktøy for software composition analysis legger til reachability-analyse, som sjekker om koden din i det hele tatt kan kalle den sårbare funksjonen, for å avgjøre hvilken av disse rettingene som kommer først. Alternativene finner du i SCA-verktøy sammenlignet.

Hvorfor lockfilen ikke forteller hele historien

De fleste verktøy bygger sitt bilde av transitive avhengigheter ut fra lockfilen. Det fungerer når lockfilen finnes, er oppdatert og er det eneste bygget installerer fra. I CI er det ofte ikke tilfellet:

  • Ingen lockfile. En requirements.txt med versjonsområder eller et prosjekt som aldri har committet lockfilen sin, løses på nytt ved hvert bygg, så de transitive versjonene kan endre seg mellom bygg.
  • Cacher. CI-cacher gjenoppretter pakker fra tidligere kjøringer i stedet for å hente dem, og det de inneholder, er ikke alltid det den gjeldende lockfilen sier. Se hva GitHub Actions-cachen skjuler.
  • Byggeverktøy. Lintere, kompilatorer, kodegeneratorer og oppsettsteg tar med egne avhengighetstrær inn i bygget. De står ikke i manifestet til applikasjonen din, men de kjører med tilgang til kildekoden og hemmelighetene dine.
  • Installasjonsskript og nedlastinger. Installasjonsskriptet til en pakke kan hente mer kode, og et byggesteg kan laste ned en binærfil direkte. Ingen av delene etterlater en oppføring i en lockfile.

Den eneste fullstendige oversikten over hvilke transitive avhengigheter som gikk inn i en utgivelse, er en som ble tatt mens utgivelsen ble bygget. SBOM-er fra bygget forklarer forskjellen på å registrere et bygg og å skanne filene etterpå.

Transitive avhengigheter og CRA

EUs Cyber Resilience Act ber produsenter utarbeide en SBOM som dekker "at the very least the top-level dependencies of the products" (Annex I, Part II, point 1). Transitive avhengigheter er ikke nevnt, så det juridiske minstekravet er lavere enn mange guider antyder. Men CRA ber deg også identifisere og håndtere sårbarheter i komponentene produktet ditt inneholder, og en sårbar transitiv pakke er en av dem. En SBOM som stopper ved første nivå, holder det meste av avhengighetstreet ditt utenfor den prosessen. Detaljene finner du i CRA-krav til SBOM.

Slik sporer CRACI transitive avhengigheter

CRACI er en GitHub Actions-runner som registrerer bygget i stedet for å skanne det. Mens hver jobb kjører, registrerer en pakkebevisst proxy hver pakke jobben henter, på alle nivåer i treet, inkludert pakker gjenopprettet fra CI-cacher. Det gir et mer fullstendig bilde av avhengighetene som er i bruk, enn skannerbaserte verktøy.

  • Alle nivåer, ærlig angitt. Hver jobbs SBOM har en fullstendighetsstatus, så du vet når en registrering ikke kunne se alt.
  • Treet, synlig. En avhengighetsgraf viser avhengighetslagene i SBOM-en, i flere visninger.
  • Eksporter som tar dem med. Eksporter i CycloneDX og SPDX inkluderer transitive avhengigheter, hver med sin deklarerte lisens.
  • Hvilke bygg som ble berørt. Når en ny sårbarhet dukker opp, viser byggehistorikken hvilke tidligere bygg som inneholdt den sårbare pakken, direkte eller transitiv, så du vet i hvilken periode du leverte den (se er vi berørt av en CVE?). Historikken følger oppbevaringstiden din, som er 180 dager som standard.
  • Policy-gates. Et bygg som inneholder en bestemt CVE, kan blokkeres før det leveres.

CRACI gjør ikke reachability-analyse. Trenger du å vite om koden din kaller en sårbar funksjon, kan du kombinere det med et SCA-verktøy som gjør det. Se SBOM-generering i CRACI eller book en demo for å registrere et av dine egne bygg.

Transitive avhengigheter: ofte stilte spørsmål

Hva er en transitiv avhengighet?

En transitiv avhengighet er en pakke programvaren din bruker fordi en annen pakke trenger den. Hvis appen din er avhengig av bibliotek A og A er avhengig av bibliotek B, er B en transitiv, eller indirekte, avhengighet av appen din. Du har aldri deklarert den, men den leveres med programvaren din.

Hva er forskjellen på en direkte og en transitiv avhengighet?

En direkte avhengighet er en du deklarerer i manifestet ditt, for eksempel package.json, pyproject.toml eller go.mod. En transitiv avhengighet er en som de direkte avhengighetene dine deklarerer, på et hvilket som helst nivå. Du velger direkte avhengigheter; pakkebehandleren velger transitive når den løser treet.

Er en transient avhengighet det samme som en transitiv avhengighet?

Ja, i praksis. «Transient avhengighet» er en vanlig forveksling med «transitiv avhengighet». Det riktige begrepet er transitiv, fra den transitive relasjonen: Hvis A er avhengig av B og B er avhengig av C, er A avhengig av C.

Hvordan retter jeg en sårbarhet i en transitiv avhengighet?

Oppgrader først den direkte avhengigheten som trekker den inn, hvis det finnes en utgivelse med en rettet versjon. Hvis ikke, tvinger du frem den rettede versjonen med pakkebehandlerens overstyringsmekanisme, for eksempel npm overrides, Yarn resolutions eller en constraints-fil for pip, og tester at foreldrepakken fortsatt fungerer med den.

Hvordan lister jeg opp alle transitive avhengigheter?

Alle pakkebehandlere kan skrive ut det oppløste treet: npm ls --all, pnpm list --depth Infinity, uv tree eller pipdeptree, go mod graph, cargo tree, mvn dependency:tree eller gradle dependencies. For å se hva et produksjonsbygg faktisk installerte, registrerer du selve bygget.

Krever EUs Cyber Resilience Act transitive avhengigheter i SBOM-en?

Forordningen setter minstekravet til "at the very least the top-level dependencies of the products" (Annex I, Part II, point 1). Transitive avhengigheter er ikke nevnt, men en sårbar transitiv pakke er likevel i produktet ditt, og CRA ber deg håndtere sårbarheter i komponentene du leverer.

Se hver avhengighet bygget ditt hentet inn

Kjør én GitHub Actions-workflow på CRACI og få en registrert SBOM over hver pakke den hentet, på alle nivåer i treet.

Book en demo