Gå til hovedindhold

Transitive afhængigheder

En sårbar pakke er ofte ikke en, du selv har erklæret. En anden afhængighed trækker den ind, og den afhængighed vælger versionen. Den kan ikke opdateres, hvor den er erklæret, fordi den ikke er erklæret nogen steder i dit repository. Sikkerhedsrettelser fastlåser i stedet sådan en pakke fra roden af dit projekt med den mekanisme, hvert økosystem stiller til rådighed til det.

ØkosystemSådan fastlåses pakkenSådan beder du om det
npm (package-lock.json)En overrides-post i package.json, og pakkens poster i package-lock.json flyttet til den rettede versionÅbn rettelses-PR på fundet, som for alle andre. Når hostet Renovate ikke finder noget at opdatere, fastlåser fremforge den inden for cirka ti minutter
pnpm (pnpm-lock.yaml)En overrides-post i pnpm-workspace.yaml (eller package.json pnpm.overrides for pnpm 9 og ældre), og lockfilen flyttet tilsvarendeSom for npm
Yarn 1 (yarn.lock)En resolutions-post i package.json, og posten i yarn.lock flyttetSom for npm. Yarn 2 og nyere afvises
PyPI (uv.lock, poetry.lock)Pakkens lock-post flyttet til den rettede version, uden fastlåsning i pyproject.tomlSom for npm
Maven (pom.xml)En <dependencyManagement>-post i den pom.xml, fundet kom fraÅbn rettelses-PR, som for npm
Maven (set i din SBOM)En <dependencyManagement>-post i rodens pom.xmlFastlås som transitiv på fundet, eller POST /orgs/{org}/dependency-updates/security-fixes/transitive-requests
Gradle (gradle.lockfile)En constraints-post i build-filen, og linjen i lockfilen flyttetSom for npm
GoIntet ekstra: go.mod angiver hvert modul, dit build bruger, markeret // indirect, og rettelsen hæver den linjeÅbn rettelses-PR

Det er en almindelig pull request med en sikkerhedsrettelse, og den samme udgivelsesalder gælder: en rettet version, der er yngre end din organisations Udgivelsesalder (dage) (3 som standard), foreslås ikke endnu, medmindre den retter en kendt udnyttet sårbarhed. Da ingen Renovate-kørsel tjekker en transitiv fastlåsning, læser fremforge selv udgivelsestidspunktet gennem din afhængighedsproxy: npm-registrets time, PyPI’s uploadtidspunkt for den rettede versions filer og for Maven og Gradle det tidspunkt, Maven Central oplyser for pom’en. En rettet version, hvis udgivelsestidspunkt ikke kan læses, foreslås ikke.

Den har også samme branch (security-fix/<package>-<version>), etiket (security-fix), grænser og merge-indstilling som alle andre, og det samme valg under Hvornår rettelser merges gælder. Pull requesten oplyser, at pakken er transitiv, og hvordan den blev fastlåst.

npm

Pull requesten ændrer to filer og intet andet:

"overrides": {
  "lodash": "4.18.0"
}

Det tilføjes i package.json. Hver post i package-lock.json for pakken i en sårbar version flyttes til den rettede version, med ændret version og tarball-URL og ændret integritets-hash, hvor posten havde en. URL’en beholder din lockfils registry.

fremforge kører ikke npm install eller noget andet fra dit repository. Den skriver lock-posterne ud fra registrets metadata, læst gennem din organisations afhængighedsproxy, så dine pakkepolitikker også gælder for den rettede version. Den skriver dem kun, når det er alt, en opløsning ville ændre:

  • Den rettede version erklærer præcis de samme afhængigheder som den version, den erstatter. Ellers afvises bestillingen med transitive_dependencies_changed, fordi træet ville ændre sig ud over denne pakke.
  • Hver kopi af pakken i lockfilen er i en sårbar version. En override flytter alle kopier, så en kopi i en anden, upåvirket version afviser bestillingen med override_conflict.
  • package-lock.json har lockfileVersion 2 eller 3.

npm ci accepterer resultatet. Fjern overriden, når de pakker, der trækker pakken ind, selv kræver den rettede version.

pnpm

pnpm registrerer også overrides i lockfilen og afviser en lockfil, hvis overrides:-afsnit afviger fra konfigurationen. Pull requesten ændrer derfor begge:

  • overriden i pnpm-workspace.yaml (oprettes, hvis repositoriet ikke har en). Den lægges i stedet i package.json pnpm.overrides, når packageManager angiver pnpm 9 eller ældre, eller, uden packageManager, når projektet har sine overrides der og ingen pnpm-workspace.yaml har;
  • pnpm-lock.yaml: dens overrides:-afsnit, pakkens poster under packages og snapshots med integriteten fra registret samt hver henvisning til den gamle version.

pnpm install --frozen-lockfile accepterer resultatet. Kun lockfileVersion: '9.0' understøttes; en pakke låst med et peer-dependency-suffiks som foo@1.0.0(react@18.3.1) afvises med lock_entry_unsupported.

Yarn

For Yarn 1 tilføjer pull requesten en resolutions-post i package.json og flytter pakkens post i yarn.lock: dens version, dens resolved-URL (på din lockfils registry, med tarballens checksum) og dens integrity. yarn install --frozen-lockfile accepterer resultatet.

Yarn 2 og nyere (en yarn.lock med __metadata) afvises med yarn_berry_checksum. Deres lockfil registrerer en checksum af det arkiv, Yarn bygger ud fra pakken, og den kan kun Yarn selv beregne. Tilføj selv en resolutions-post, og kør yarn install.

De samme regler som for npm gælder for pnpm og Yarn: den rettede version skal erklære de samme afhængigheder, og hver kopi af pakken i lockfilen skal være i en sårbar version.

Python

For uv.lock og poetry.lock flytter pull requesten pakkens lock-post til den rettede version og tilføjer intet i pyproject.toml. En pakke, som pyproject.toml erklærer, afvises med already_declared, fordi Åbn rettelses-PR opdaterer den der. Den nye post indeholder den rettede versions filer med deres hashes, læst fra din organisations PyPI-afhængighedsproxy:

  • uv: sdist og wheels med URL, hash, størrelse og uploadtidspunkt, hvor din lockfil registrerer dem. URL’erne beholder din lockfils index: afhængighedsproxyens egen URL, når du låser mod den, eller files.pythonhosted.org, når du låser mod PyPI. En lockfil fra et hvilket som helst andet index afvises med lock_entry_unsupported.
  • Poetry: versionen, beskrivelsen, python-versions og files. Poetrys content-hash dækker kun pyproject.toml, så den ændres ikke.

Reglen er den samme som for npm, anvendt på Pythons metadata: den rettede version skal have de samme Requires-Dist og Requires-Python som den version, den erstatter, læst fra dens wheels metadata. Ellers afvises bestillingen med transitive_dependencies_changed. uv sync --locked og poetry install accepterer resultatet. Pakken forbliver på den rettede version, indtil en senere uv lock eller poetry lock opløser igen.

Maven

Afhængighedsscanning opløser hver pom.xml, så en sårbar pakke, dit build trækker ind, er et fund på den pom.xml. Åbn rettelses-PR på det virker som for npm: når hostet Renovate ikke finder noget at opdatere, fordi pom’en ikke nævner pakken, fastlåser fremforge den i den pom.xml inden for cirka ti minutter. En pakke, der kun ses i en SBOM, du uploader, for eksempel en fra cyclonedx-maven-plugin (se afhængighedsstier), viser i stedet Fastlås som transitiv i kolonnen Rettelse og fastlåses i rodens pom.xml. I begge tilfælde tilføjer pull requesten:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.18.11</version>
    </dependency>
  </dependencies>
</dependencyManagement>

Det sætter pakkens version overalt, hvor den optræder i buildet. Styrer pom’en den allerede med en lavere, bogstavelig version, hæves den version på stedet. Bestillingen afvises, når:

  • pom’en erklærer pakken som sin egen afhængighed (already_declared). Åbn rettelses-PR opdaterer den der;
  • den styrede version læses fra en property, for eksempel ${jackson.version}, som andre poster også kan læse (managed_by_property);
  • den allerede styres med den rettede version eller højere (already_managed).

Tjek, at de afhængigheder, der trækker pakken ind, fungerer med den nye version, for et bibliotek er som regel testet mod den version, det bad om. Fjern posten, når de selv kræver den rettede version.

Gradle

For et Gradle-build med en lockfil (gradle.lockfile) tilføjer pull requesten en constraint i dependencies-blokken i build-filen ved siden af lockfilen (build.gradle.kts eller build.gradle):

dependencies {
    constraints {
        implementation("org.yaml:snakeyaml:2.0") {
            because("fremforge security fix: pins a transitive dependency to a version that fixes its open advisories")
        }
    }
}

Den flytter også pakkens linje i gradle.lockfile, så lockfilen og buildet stemmer overens, og Gradle accepterer lockfilen i strict mode. Som for Maven skal den rettede versions pom erklære de samme afhængigheder og den samme parent som den, den erstatter. Bestillingen afvises, når:

  • build-filen allerede nævner pakken (already_declared);
  • buildet verificerer afhængigheder med gradle/verification-metadata.xml (gradle_verification_metadata). Den nye version kræver checksums i den fil, og dem beregner Gradle; kør selv ./gradlew --write-verification-metadata sha256;
  • pakken er låst i en konfiguration, som en implementation-constraint ikke når, for eksempel et plugins egen classpath (gradle_configuration_unsupported);
  • build-filen har ingen dependencies {-blok på øverste niveau (build_file_unsupported).

fremforge kører ikke Gradle. Et Gradle-build af pull requesten i din CI tjekker lockfilen mod buildet og fejler, hvis de ikke stemmer overens.

Når der ikke åbnes en pull request

Bestillingen viser så årsagen. Gennem API’et er reason transitive_<why>, og detail forklarer den:

ÅrsagBetydning
transitive_already_declaredPakken er en direkte afhængighed. Åbn rettelses-PR opdaterer den, hvor den er erklæret
transitive_transitive_dependencies_changedDen rettede version erklærer andre afhængigheder (for Python også en anden Requires-Python), så lockfilen kræver en fuld opløsning
transitive_override_conflictEn anden kopi af pakken i en upåvirket version ville også blive flyttet, eller en override, resolution eller constraint fastlåser den allerede anderledes
transitive_yarn_berry_checksumYarn 2 eller nyere: lockfilen kræver en checksum, som kun Yarn kan beregne
transitive_gradle_verification_metadataGradle: buildet verificerer afhængigheder, og den nye version kræver checksums, som Gradle beregner
transitive_gradle_configuration_unsupportedGradle: pakken er låst i en konfiguration, som en implementation-constraint ikke når
transitive_build_file_unsupportedGradle: build-filen har ingen dependencies {-blok på øverste niveau
transitive_lock_entry_unsupportedLock-posten har en form, fremforge ikke redigerer, for eksempel et pnpm-peer-suffiks, flere låste versioner eller en uv-lockfil fra et index, den ikke betjener
transitive_managed_by_propertyMaven: den styrede version kommer fra en property
transitive_already_managedMaven: styres allerede med den rettede version eller højere
transitive_lock_version_unsupportednpm: lockfileVersion 1. pnpm: en anden lockfilversion end 9.0
transitive_manifest_not_supportedEn lockfil, der ikke er nævnt ovenfor, for eksempel bun.lock, pdm.lock eller Pipfile.lock
transitive_target_metadata_missingAfhængighedsproxyen gav ingen metadata for den rettede version, for eksempel fordi en pakkepolitik afviser den
transitive_manifest_missing, transitive_lock_missingManifestet eller lockfilen ligger ikke på den forventede sti på standardbranchen
transitive_release_age_pendingDen rettede version er yngre end din udgivelsesalder; bestil igen efter den dato, detaljen nævner
transitive_release_age_unknownAfhængighedsproxyen gav intet udgivelsestidspunkt for den rettede version
transitive_branch_existsBranchen security-fix/<package>-<version> findes allerede
transitive_repo_not_writableRepositoriet er arkiveret eller et mirror

For en bestilling via Åbn rettelses-PR (alle økosystemer undtagen Maven) beholder bestillingen No PR: nothing to change, og detaljen nævner årsagen.

API

npm, pnpm, Yarn, Python og Gradle kræver intet ud over POST /orgs/{org}/dependency-updates/security-fixes/requests. For Maven:

curl -sS -X POST "https://frem.sh/_app/api/v1/orgs/acme/dependency-updates/security-fixes/transitive-requests" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN" -H "Content-Type: application/json" \
  -d '{"finding_id": "<dependency finding id>"}'

Den svarer 201 med bestillingen og dens udfald: pr_opened med pr_number og pr_url eller rejected med reason og detail. En afvisning, før en bestilling findes, er et problem af typen security-fix-<reason>, for eksempel security-fix-not-transitive. Scopet er dependency-updates:write. Bestillingen vises derefter af GET …/security-fixes/requests som alle andre.