GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Vendored Gradle silently downgrades a version-range dependency to an older unpatched release (1.10.0 → 1.9), because the vendored repository has no maven-metadata.xml; vendor --check and VEX still report it patched · Issue #511 · SocketDev/socket-patch

Vendored Gradle silently downgrades a version-range dependency to an older unpatched release (1.10.0 → 1.9), because the vendored repository has no maven-metadata.xml; vendor --check and VEX still report it patched #511

New issue
Copy link
New issue
Copy link
Closed
#646
Closed
Vendored Gradle silently downgrades a version-range dependency to an older unpatched release (1.10.0 → 1.9), because the vendored repository has no maven-metadata.xml; vendor --check and VEX still report it patched#511
#646
Copy link
Labels
agent:triagedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:gradleGradleGradlepriority:p3

Description

@mikolalysenko
Mikola Lysenko (mikolalysenko)
opened on Oct 1, 2026
Issue body actions

[agent] Found by the scheduled Gradle bug-hunt routine (ledger #319).

Summary

When a Gradle build declares the patched library with a version range ([1.9,1.10.0], or a rich strictly '[1.9,1.11)'; prefer '1.10.0'), it resolves the patched base version (1.10.0) before vendoring. After socket-patch vendor the same build resolves commons-text 1.9 from Maven Central instead: an older release that isn't patched.

The cause is the generated exclusiveContent { filter { includeVersion(g, a, "1.10.0") } }. It removes 1.10.0 from Central's candidate list. The socketPatchVendor file repository, .socket/vendor/gradle/<g>/<a>/, has no maven-metadata.xml, so it lists no versions for the range. Gradle then picks the highest version that's left, 1.9.

Nothing reports the downgrade:

  • vendor exits 0 with no warning.
  • vendor --check returns vendor_check_ok ("committed artifact and wiring verified").
  • vex emits not_affected / inline_mitigations_already_exist for pkg:maven/org.apache.commons/[email protected], a version the build no longer uses.

Impact

A project that pins a range, or a narrow strictly range with a prefer, ends up on a different and older version after vendoring, with no error. The patch is never used, and the build may now carry vulnerabilities that 1.10.0 had already fixed. The VEX attestation is false.

Repro (Linux, Gradle 8.14.3 and 9.8.0, JDK 21, main 61cfb9b)

mkdir p && cd p
cat > settings.gradle <<'EOF'
rootProject.name = 'p'
EOF
cat > build.gradle <<'EOF'
plugins { id 'java' }
repositories { mavenCentral() }
dependencies { implementation 'org.apache.commons:commons-text:[1.9,1.10.0]' }
tasks.register('printCp') { def cp = configurations.runtimeClasspath; doLast { cp.files.each { println "CP " + it } } }
EOF
gradle -q dependencies --configuration runtimeClasspath | grep commons-text
#   \--- org.apache.commons:commons-text:[1.9,1.10.0] -> 1.10.0
# stage a patch for pkg:maven/org.apache.commons/[email protected] in .socket/manifest.json + blob
#   (the bug-hunt used prebuilt_common::prepare_command, the same as e2e_vendor_jvm_build.rs)
socket-patch vendor --json --offline        # exit 0, applied 1, no warnings
rm -rf .gradle build
gradle -q dependencies --configuration runtimeClasspath | grep commons-text
#   \--- org.apache.commons:commons-text:[1.9,1.10.0] -> 1.9        <-- downgraded, unpatched
gradle -q printCp | grep commons-text
#   CP ~/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-text/1.9/.../commons-text-1.9.jar
socket-patch vendor --check --json          # exit 0, vendor_check_ok
socket-patch vex --product pkg:maven/x/p@1  # status not_affected for [email protected]

Confirming the cause: if I hand-write .socket/vendor/gradle/org/apache/commons/commons-text/maven-metadata.xml listing <version>1.10.0</version>, the same build resolves [1.9,1.10.0] -> 1.10.0 from .socket/vendor/gradle/.../commons-text-1.10.0.jar, and that jar has the patch marker.

Expected vs actual

  • Expected: vendoring never changes which version Gradle selects. docs/design/maven-vendoring.md says the Gradle backend keeps the original GAV and serves it from the committed repository. For Maven it also says: "Range selectors, unresolved properties, … produce specific warnings; the backend does not silently claim those unsupported declarations are patched." The same section lists "dynamic-version repository metadata" as remaining scope. So either the vendored repo should carry a maven-metadata.xml for each vendored module, which fixes it in my test, or vendor should warn or refuse. In neither case should --check and VEX report the patch as in effect.
  • Actual: exit 0, no warning, the build is silently downgraded to an unpatched release, vendor --check passes, and VEX says not_affected.

Matrix

Declaration Gradle 8.14.3 Gradle 9.8.0
[1.9,1.10.0] fail (→ 1.9) fail (→ 1.9)
{ strictly '[1.9,1.11)'; prefer '1.10.0' } fail (→ 1.9) fail (→ 1.9)
1.10.0!! (strict exact) pass (vendored, patched) n/t
1.+ / latest.release unaffected (resolves 1.15.0 before and after, so the patch doesn't apply) n/t

Linux only. I didn't run macOS or Windows, or Gradle 6.9.4 / 7.6.6. Gradle's version selection doesn't depend on the OS, and the script is the same on every Gradle version ≥ 6.8, so I expect the same result there.

Suspect code

  • crates/socket-patch-core/src/vendor/jvm/socket-patch.settings.gradle:51: includeVersion(...) inside exclusiveContent excludes the base version from every other repository.
  • crates/socket-patch-core/src/vendor/jvm/gradle.rs:68 (plan): it writes the version directory but no artifact-level maven-metadata.xml, and it doesn't scan build scripts for range or rich-version declarations, so nothing warns.
  • vendor --check and vex check only the committed bytes and the wiring, not which version is selected.

Activity

  1. Mikola Lysenko (mikolalysenko)
    added
    bugSomething isn't workingSomething isn't working
    bughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agent
    pm:gradleGradleGradle
    on Oct 1, 2026
  2. Mikola Lysenko (mikolalysenko)
    added a commit that references this issue on Oct 1, 2026

    gradle: run 6 ledger (#511)

    be571ed
  3. mikolalysenko commented on Oct 2, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 2, 2026
    CollaboratorAuthor
    More actions

    [agent] Triaged as priority:p3 (Gradle). Not a duplicate, and there's no fix PR. I confirmed on main 61cfb9b: vendor/jvm/gradle.rs writes no artifact-level maven-metadata.xml into .socket/vendor/gradle/<g>/<a>/, and the settings script's exclusiveContent { includeVersion(...) } removes the base version from every other repository, so a range selector can't see it. Related to #347 and #461 (other gaps in exclusiveContent), but the cause here is different.


    Generated by Claude Code

  4. Mikola Lysenko (mikolalysenko)
    added
    priority:p3
    agent:triaged
    on Oct 2, 2026
  5. mikolalysenko commented on Oct 2, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 2, 2026
    CollaboratorAuthor
    More actions

    [agent] Two more data points for this issue, on main 61cfb9b with Gradle 8.14.3 on Linux:

    • Version catalog range reproduces it. With libs.versions.toml set to text = { require = "[1.9,1.10.0]" } and implementation libs.text, a fresh clone resolves commons-text-1.10.0.jar before vendoring and commons-text-1.9.jar (unpatched, from the Gradle cache) after vendor exits 0. I saw it twice. The vendored 1.10.0 jar does carry the patch marker; it just isn't selected.
    • A gradle.lockfile masks it. With dependencyLocking { lockAllConfigurations() } and the lockfile written before vendoring (commons-text:1.10.0=…runtimeClasspath…), the same range resolves the vendored .socket/vendor/gradle/…/commons-text-1.10.0.jar after vendoring. So only unlocked range or catalog declarations are affected.

    Generated by Claude Code

  6. Mikola Lysenko (mikolalysenko)
    added
    agent:claimed
    on Oct 2, 2026
  7. mikolalysenko commented on Oct 2, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 2, 2026
    CollaboratorAuthor
    More actions

    [agent] Claiming this issue as part of the full Gradle support campaign (agent / hosted / vendored modes, tested on Gradle 6.9/7.6/8.x/9.x on Linux, macOS and Windows). Branch: feat/gradle-support. Claim-ID: 2026-10-02T13:56:32Z-gradle21


    Generated by Claude Code

  8. mikolalysenko commented on Oct 3, 2026

    @mikolalysenko
    Mikola Lysenko (mikolalysenko)
    on Oct 3, 2026
    CollaboratorAuthor
    More actions

    [agent] Another data point: the range doesn't have to be in the user's build. A transitive range from a third-party POM causes the same downgrade, and the user can't avoid it by editing their own declarations.

    Main 045d7ec, Gradle 8.14.3, JDK 21, Linux. Reproduced 2 out of 2 times, from a clean .gradle.

    • com.example:lib:1.0 is in a file repository, and its POM declares org.apache.commons:commons-text:[1.9,1.10.0]. The project only declares implementation 'com.example:lib:1.0' with repositories { maven { url = corp }; mavenCentral() }.
    • Before vendoring: commons-text:[1.9,1.10.0] -> 1.10.0.
    • vendor --json --offline for pkg:maven/org.apache.commons/[email protected] exits 0 with no warning. The planner can't see the range, because it's in a dependency's POM.
    • After vendoring: commons-text:[1.9,1.10.0] -> 1.9, from ~/.gradle/caches/modules-2/.../commons-text-1.9.jar (unpatched). vendor --check exits 0. vex --product … emits not_affected for [email protected].

    So a static warning on range declarations in the project's own build files wouldn't cover this case. A fix probably needs the vendored repository to list the version (an artifact-level maven-metadata.xml), as the issue body suggests.


    Generated by Claude Code

  9. Mikola Lysenko (mikolalysenko)
    added a commit that references this issue on Oct 5, 2026

    Full Gradle support in agent, hosted and vendored modes (#646)

    0685ba8
  10. Mikola Lysenko (mikolalysenko)
    closed this as completedin #646on Oct 5, 2026
  11. Mikola Lysenko (mikolalysenko)
    removed
    agent:claimed
    on Oct 6, 2026
  12. Mikola Lysenko (mikolalysenko)
    added a commit that references this issue on Oct 7, 2026

    sbt, Mill and scala-cli support in agent, hosted and vendored modes (#…

    5a96c52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:gradleGradleGradlepriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.