Agent-mode apply in a Gradle-only project patches the ~/.m2 copy Gradle never reads, reports success, and VEX attests not_affected while the build uses the unpatched ~/.gradle jar
维护者通常 1 天内回复
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 72/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 领域
- build-system, cli, devtools
调研方向
Start with crates/socket-patch-core/src/crawlers/maven_crawler.rs:580-605 and m2_repo_path() at :709, then run the Linux Gradle reproduction with apply --json --offline followed by vex --offline. Trace how Gradle markers select the install root and how find_by_purls locates artifacts. Done means a Gradle build without mavenLocal() cannot receive a successful apply or not_affected attestation from an unused ~/.m2 copy.
由索引模型根据 Issue 内容生成。
描述
[agent] Found by the scheduled Gradle bug-hunt routine (ledger #319).
Summary
In a Gradle-only project (settings.gradle + build.gradle, repositories { mavenCentral() }), agent-mode apply resolves the Maven patch against the Maven local repository ($MAVEN_REPO_LOCAL / ~/.m2/repository) whenever that repository happens to hold the same GAV, for example from unrelated Maven use on the same machine or CI image. It patches that jar in place and exits 0 with applied: 1, and vex then emits not_affected / inline_mitigations_already_exist. Gradle never reads ~/.m2 unless the build declares mavenLocal(). It resolves from $GRADLE_USER_HOME/caches/modules-2/files-2.1/…, so the real build keeps compiling and running the unpatched jar.
This is the agent-mode analogue of #397 (NuGet) and #387 (cargo). It's separate from #349: #349 is the discovery gap (scan finds 0 packages and never fires). Here a manifest is already present (committed by a teammate, or saved by get), and apply + vex claim protection that the build doesn't have.
Impact
A false VEX attestation, plus a success exit code, for a vulnerability that's still present in the shipped Gradle build. As a side effect, the jar under ~/.m2 is mutated (with its .sha1 sidecar now stale) for every other Maven project on the machine.
Repro (Linux, Gradle 8.14.3, JDK 21, main 61cfb9b)
export GRADLE_USER_HOME=$PWD/gh MAVEN_REPO_LOCAL=$PWD/m2
mkdir proj && cd proj
echo "rootProject.name='p'" > settings.gradle
cat > build.gradle <<'EOF'
plugins { id 'java' }
repositories { mavenCentral() }
dependencies { implementation 'org.apache.commons:commons-text:1.10.0' }
tasks.register('printCp') { doLast { configurations.runtimeClasspath.files.each { println "CP " + it } } }
EOF
gradle -q printCp # fills $GRADLE_USER_HOME/caches/modules-2
mvn -q -Dmaven.repo.local=$MAVEN_REPO_LOCAL dependency:get -Dartifact=org.apache.commons:commons-text:1.10.0 # the same GAV, from unrelated Maven use
# stage an agent-mode record: files {"commons-text-1.10.0.jar": {beforeHash, afterHash}} + blob,
# where the patched jar adds a marker line to META-INF/NOTICE.txt
git init -q && git remote add origin https://github.com/example/gp.git
socket-patch apply --json --offline # "status":"success", applied: 1, exit 0
socket-patch vex --offline --product pkg:github/example/gp # status "not_affected"
unzip -p $MAVEN_REPO_LOCAL/org/apache/commons/commons-text/1.10.0/commons-text-1.10.0.jar META-INF/NOTICE.txt | grep -c MARKER # 1 (m2 copy patched)
gradle -q printCp | grep commons-text # …/gh/caches/modules-2/files-2.1/org.apache.commons/commons-text/1.10.0/3363381a…/commons-text-1.10.0.jar
unzip -p <that jar> META-INF/NOTICE.txt | grep -c MARKER # 0 (the build uses the unpatched jar)
I ran this twice from clean directories, and both runs gave the same result.
Control: with repositories { mavenLocal(); mavenCentral() } (and -Dmaven.repo.local pointing at the same m2), Gradle resolves m2/…/commons-text-1.10.0.jar and the marker is present. So the in-place patch itself is fine. The defect is that the CLI targets a copy that the build doesn't use, and attests it.
Expected vs actual
- Expected: docs/ecosystems.md (the Maven row) describes agent mode as in-place jar patching of
~/.m2, and the crawler deliberately acceptsbuild.gradle*/settings.gradle*as project markers (maven_crawler.rs:581). For a Gradle build that has nomavenLocal(), the m2 copy isn't the installed package.applyshould refuse or warn (for example, "Gradle builds resolve from$GRADLE_USER_HOME; usevendor"), or patch the copy Gradle actually uses. README.md says to "Generate VEX after installing to verify the copies your build consumes", sovexmust not attestnot_affectedfrom a copy the build doesn't consume. - Actual:
applyexits 0 withapplied: 1,vexgivesnot_affected, and the Gradle build is unpatched. No warning is printed anywhere.
Matrix
| OS | Gradle (JDK) | Build repos | apply | vex | Jar the build uses |
|---|---|---|---|---|---|
| Linux | 8.14.3 (21) | mavenCentral() |
success, applied 1 ❌ | not_affected ❌ | unpatched (~/.gradle cache) ❌ |
| Linux | 8.14.3 (21) | mavenLocal(); mavenCentral() |
success | not_affected | patched m2 jar ✅ (control) |
| macOS / Windows, Gradle 6–9 | — | — | untested. The selection logic is OS- and version-independent, and the modules-2/files-2.1 layout has been unchanged since Gradle 1.x. |
Related
apply --global-prefix $GRADLE_USER_HOME/caches/modules-2/files-2.1fails loudly (package_not_installed, exit 1), becausefind_by_purlsonly knows the Maven layout. That's correct fail-loud behaviour, noted here for completeness.- #349 (discovery), #397 / #387 (the same class of bug in other ecosystems).
Suspect code
crates/socket-patch-core/src/crawlers/maven_crawler.rs:580-605: Gradle markers selectm2_repo_path()(:709) as the install root, although a Gradle build withoutmavenLocal()never reads it.crates/socket-patch-core/src/crawlers/maven_crawler.rsfind_by_purls: Maven layout only, so the copy Gradle uses can never be patched or verified.
- 主要语言
- Rust
- 星标
- 8
- 派生
- 0
- 平均合并
- 1 天 1 小时
- 30 天内合并 PR
- 257
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
SocketDev/socket-patch 的其他 Issue
-
agent:triaged bug bughunt pm:npm priority:p1
难度 2/5 1-3 小时 新手友好度 85/100
SocketDev/socket-patch#1127 · 1 条评论 ·
维护者通常 1 天内回复
-
agent:triaged bug bughunt pm:bundler priority:p1
难度 2/5 1-3 小时 新手友好度 75/100
SocketDev/socket-patch#1125 · 1 条评论 ·
维护者通常 1 天内回复
-
agent:triaged bug bughunt pm:pipenv priority:p1
难度 2/5 1 小时以内 新手友好度 85/100
SocketDev/socket-patch#1122 · 1 条评论 ·
维护者通常 1 天内回复
-
agent:triaged bug bughunt pm:npm priority:p1
难度 2/5 1-3 小时 新手友好度 75/100
SocketDev/socket-patch#1072 · 1 条评论 ·
维护者通常 1 天内回复
-
agent:triaged arch-audit bug priority:p3
难度 2/5 1-3 小时 新手友好度 85/100
SocketDev/socket-patch#1062 · 1 条评论 ·
维护者通常 1 天内回复
查看 SocketDev/socket-patch 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 1/5 1 小时以内 新手友好度 75/100
ajeetraina/awesome-docker-sbx#220 ·
-
`helios / deploy`: switch zone wait in `deploy.sh` has almost no headroom over healthy startup times可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭Test Flake
难度 2/5 1-3 小时 新手友好度 74/100
oxidecomputer/omicron#11453 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
microsoft/adaptive-apps#58 ·
维护者通常 2 天内回复
-
难度 2/5 1-3 小时 新手友好度 88/100
维护者通常 1 天内回复