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.
| Økosystem | Sådan fastlåses pakken | Så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 tilsvarende | Som for npm |
Yarn 1 (yarn.lock) | En resolutions-post i package.json, og posten i yarn.lock flyttet | Som 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.toml | Som 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.xml | Fastlå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 flyttet | Som for npm |
| Go | Intet 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.jsonharlockfileVersion2 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 ipackage.jsonpnpm.overrides, nårpackageManagerangiver pnpm 9 eller ældre, eller, udenpackageManager, når projektet har sine overrides der og ingenpnpm-workspace.yamlhar; pnpm-lock.yaml: densoverrides:-afsnit, pakkens poster underpackagesogsnapshotsmed 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:
sdistogwheelsmed 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, ellerfiles.pythonhosted.org, når du låser mod PyPI. En lockfil fra et hvilket som helst andet index afvises medlock_entry_unsupported. - Poetry: versionen, beskrivelsen,
python-versionsogfiles. Poetryscontent-hashdækker kunpyproject.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:
| Årsag | Betydning |
|---|---|
transitive_already_declared | Pakken er en direkte afhængighed. Åbn rettelses-PR opdaterer den, hvor den er erklæret |
transitive_transitive_dependencies_changed | Den rettede version erklærer andre afhængigheder (for Python også en anden Requires-Python), så lockfilen kræver en fuld opløsning |
transitive_override_conflict | En 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_checksum | Yarn 2 eller nyere: lockfilen kræver en checksum, som kun Yarn kan beregne |
transitive_gradle_verification_metadata | Gradle: buildet verificerer afhængigheder, og den nye version kræver checksums, som Gradle beregner |
transitive_gradle_configuration_unsupported | Gradle: pakken er låst i en konfiguration, som en implementation-constraint ikke når |
transitive_build_file_unsupported | Gradle: build-filen har ingen dependencies {-blok på øverste niveau |
transitive_lock_entry_unsupported | Lock-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_property | Maven: den styrede version kommer fra en property |
transitive_already_managed | Maven: styres allerede med den rettede version eller højere |
transitive_lock_version_unsupported | npm: lockfileVersion 1. pnpm: en anden lockfilversion end 9.0 |
transitive_manifest_not_supported | En lockfil, der ikke er nævnt ovenfor, for eksempel bun.lock, pdm.lock eller Pipfile.lock |
transitive_target_metadata_missing | Afhængighedsproxyen gav ingen metadata for den rettede version, for eksempel fordi en pakkepolitik afviser den |
transitive_manifest_missing, transitive_lock_missing | Manifestet eller lockfilen ligger ikke på den forventede sti på standardbranchen |
transitive_release_age_pending | Den rettede version er yngre end din udgivelsesalder; bestil igen efter den dato, detaljen nævner |
transitive_release_age_unknown | Afhængighedsproxyen gav intet udgivelsestidspunkt for den rettede version |
transitive_branch_exists | Branchen security-fix/<package>-<version> findes allerede |
transitive_repo_not_writable | Repositoriet 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.