[agent] Filed by Claude Code on behalf of Mikola Lysenko (@mikolalysenko) while adding Maven patch SBOM annotations to depscan. Repro artifacts were produced with real Maven and a stub patch API.
Summary
scan --mode hosted / get --mode hosted Maven rewriting (rewrite_maven_pom) finds its edit points with a bare regex and plain replacen. It does not skip:
- XML comments
<profiles>
<build><plugins><plugin><dependencies>
The vendored backend already masks comments and profiles for its anchor (find_wireable_anchor). The hosted rewriter does not. For every shape below, the CLI exits 0 with redirect.redirected = 1 and no warning.
Impact
Two failure modes, both with a successful scan:
- Silent fail-open. The real dependency still resolves the unpatched upstream jar from Central.
- Broken build. The build fails because a suffixed version is unresolvable.
The CLI's own vex then refuses to attest the result (patched_ref_unattributable / redirect_unwired). So the scan envelope and the ledger disagree with VEX.
Repro
Setup:
- CLI
socket-patch 4.0.0 built from 3efdc31d.
- A patch API stub that returns the standard
maven2 grant for org.apache.commons:commons-lang3:3.12.0: mavenSuffixedVersion = 3.12.0-socket.4d5e6f70, patch uuid 4d5e6f70-8192-4a3b-9c4d-5e6f708192a3, and mavenPomSha256 set. This is the same shape as tests/fixtures/redirect/maven/pom/basic/overrides.json.
MAVEN_REPO_LOCAL holds the base pom so discovery finds it.
socket-patch scan --mode hosted --json --yes --cwd <proj> --api-url <stub> --org test-org --api-token fake
socket-patch vex --no-verify --product pkg:maven/com.example/[email protected] -O vex.json --cwd <proj> ...
For the build step, Maven 3.9.6 ran maven-dependency-plugin:3.6.1:copy-dependencies on a fresh local repository. It used a settings.xml mirror of socket-patch-<uuid> pointing at the stub, which serves the suffixed jar and pom. A control pom (a plain direct literal) resolves the patched jar in this setup.
| case |
input pom |
what the rewriter did |
scan |
real Maven 3.9.6 |
vex |
| a |
commons-lang3 3.12.0 <dependency> inside an XML comment; the real dep is transitive via commons-text 1.10.0 |
Rewrote the commented-out <version> to 3.12.0-socket.4d5e6f70. Added no <dependencyManagement> pin, because versioned was non-empty. |
redirected=1, no warnings |
BUILD SUCCESS; commons-lang3-3.12.0.jar downloaded from Central, PRISTINE |
exit 1, patched_ref_unattributable |
| b |
<profiles><profile><repositories>… appears before any top-level <repositories>, plus a direct literal dep |
Inserted the Socket <repository> inside the inactive profile and suffixed the dep |
redirected=1 |
BUILD FAILURE: Could not find artifact …:3.12.0-socket.4d5e6f70 in central |
"<repository> is inside <profiles>" |
| c |
commons-lang3 3.12.0 as a <build><plugins><plugin><dependencies> entry (maven-antrun-plugin) |
Suffixed the plugin dependency. The Socket repo is not a <pluginRepository>. |
redirected=1 |
antrun:run BUILD FAILURE: plugin dependency 3.12.0-socket.4d5e6f70 not found |
unattributable |
| d |
a <profiles> <dependencyManagement><dependencies> precedes the top-level one; the dep is transitive |
Put the <dependencyManagement> pin inside the profile |
redirected=1, only redirect_maven_dep_management_added |
BUILD SUCCESS, PRISTINE 3.12.0 from Central |
"suffix … is inside <profiles>" |
| e |
a commented-out <repositories> block precedes the dependencies |
Inserted the Socket <repository> inside the comment |
redirected=1 |
the suffixed version is unresolvable, so the build fails |
unattributable |
Diff for case a (the whole edit):
<!-- pulled in by commons-text; was declared directly before:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
- <version>3.12.0</version>
+ <version>3.12.0-socket.4d5e6f70</version>
</dependency>
-->
These can be added as goldens under tests/fixtures/redirect/maven/pom/<case>/ next to basic, reusing basic/overrides.json.
Expected vs actual
- Expected:
- Every matcher and anchor ignores comments,
<profiles> and <build>/<reporting>/<pluginManagement> subtrees. Those are the same scopes VEX discovery (vendor/maven_pom.rs) already ignores.
- A dependency whose only occurrences are masked is treated as not declared, so it gets the transitive
<dependencyManagement> pin at the top level.
- A repository or pin is never placed inside a masked region.
- If no safe anchor exists, the dep is refused with a warning instead of reported as redirected.
- Actual: the rewrites above, exit 0,
redirected: 1, and no warning.
CLI revision
3efdc31d (socket-patch 4.0.0).
Suggested fix
- Reuse
vendor/maven_repo.rs comment_spans / profiles_spans / find_outside (or the maven_pom.rs parser) in:
find_maven_dependency_matches
insert_maven_repository
insert_maven_dependency_management
- Also mask
<build> (plugins and pluginManagement) and <reporting>.
- Keep the TS twin in depscan (
workspaces/app/src/patches/registry-rewrite/maven-pom.ts) in sync.
- Add goldens a–e.
File refs (at 3efdc31)
crates/socket-patch-core/src/patch/redirect/mod.rs:5860-5899 (MAVEN_DEPENDENCY_BLOCK_RE, find_maven_dependency_matches: every <dependency> block anywhere)
crates/socket-patch-core/src/patch/redirect/mod.rs:6268-6280 (insert_maven_repository: pom.contains("<repositories>") / replacen)
crates/socket-patch-core/src/patch/redirect/mod.rs:6284-6300 (insert_maven_dependency_management: first <dependencyManagement>\s*<dependencies> anywhere)
- For contrast:
crates/socket-patch-core/src/vendor/maven_repo.rs:968-1020 (build_repo_edit / find_wireable_anchor)
- Confirmation by substring:
crates/socket-patch-cli/src/commands/scan/hosted.rs:2413-2431 (see the separate issue on maven redirect confirmation)
[agent] Filed by Claude Code on behalf of Mikola Lysenko (@mikolalysenko) while adding Maven patch SBOM annotations to depscan. Repro artifacts were produced with real Maven and a stub patch API.
Summary
scan --mode hosted/get --mode hostedMaven rewriting (rewrite_maven_pom) finds its edit points with a bare regex and plainreplacen. It does not skip:<profiles><build><plugins><plugin><dependencies>The vendored backend already masks comments and profiles for its anchor (
find_wireable_anchor). The hosted rewriter does not. For every shape below, the CLI exits 0 withredirect.redirected = 1and no warning.Impact
Two failure modes, both with a successful scan:
The CLI's own
vexthen refuses to attest the result (patched_ref_unattributable/redirect_unwired). So the scan envelope and the ledger disagree with VEX.Repro
Setup:
socket-patch 4.0.0built from3efdc31d.maven2grant fororg.apache.commons:commons-lang3:3.12.0:mavenSuffixedVersion = 3.12.0-socket.4d5e6f70, patch uuid4d5e6f70-8192-4a3b-9c4d-5e6f708192a3, andmavenPomSha256set. This is the same shape astests/fixtures/redirect/maven/pom/basic/overrides.json.MAVEN_REPO_LOCALholds the base pom so discovery finds it.For the build step, Maven 3.9.6 ran
maven-dependency-plugin:3.6.1:copy-dependencieson a fresh local repository. It used asettings.xmlmirror ofsocket-patch-<uuid>pointing at the stub, which serves the suffixed jar and pom. A control pom (a plain direct literal) resolves the patched jar in this setup.vex<dependency>inside an XML comment; the real dep is transitive via commons-text 1.10.0<version>to3.12.0-socket.4d5e6f70. Added no<dependencyManagement>pin, becauseversionedwas non-empty.commons-lang3-3.12.0.jardownloaded from Central, PRISTINEpatched_ref_unattributable<profiles><profile><repositories>…appears before any top-level<repositories>, plus a direct literal dep<repository>inside the inactive profile and suffixed the depCould not find artifact …:3.12.0-socket.4d5e6f70 in central<repository>is inside<profiles>"<build><plugins><plugin><dependencies>entry (maven-antrun-plugin)<pluginRepository>.antrun:runBUILD FAILURE: plugin dependency3.12.0-socket.4d5e6f70not found<profiles><dependencyManagement><dependencies>precedes the top-level one; the dep is transitive<dependencyManagement>pin inside the profileredirect_maven_dep_management_added<profiles>"<repositories>block precedes the dependencies<repository>inside the commentDiff for case a (the whole edit):
<!-- pulled in by commons-text; was declared directly before: <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.12.0</version> + <version>3.12.0-socket.4d5e6f70</version> </dependency> -->These can be added as goldens under
tests/fixtures/redirect/maven/pom/<case>/next tobasic, reusingbasic/overrides.json.Expected vs actual
<profiles>and<build>/<reporting>/<pluginManagement>subtrees. Those are the same scopes VEX discovery (vendor/maven_pom.rs) already ignores.<dependencyManagement>pin at the top level.redirected: 1, and no warning.CLI revision
3efdc31d(socket-patch 4.0.0).Suggested fix
vendor/maven_repo.rscomment_spans/profiles_spans/find_outside(or themaven_pom.rsparser) in:find_maven_dependency_matchesinsert_maven_repositoryinsert_maven_dependency_management<build>(plugins and pluginManagement) and<reporting>.workspaces/app/src/patches/registry-rewrite/maven-pom.ts) in sync.File refs (at 3efdc31)
crates/socket-patch-core/src/patch/redirect/mod.rs:5860-5899(MAVEN_DEPENDENCY_BLOCK_RE,find_maven_dependency_matches: every<dependency>block anywhere)crates/socket-patch-core/src/patch/redirect/mod.rs:6268-6280(insert_maven_repository:pom.contains("<repositories>")/replacen)crates/socket-patch-core/src/patch/redirect/mod.rs:6284-6300(insert_maven_dependency_management: first<dependencyManagement>\s*<dependencies>anywhere)crates/socket-patch-core/src/vendor/maven_repo.rs:968-1020(build_repo_edit/find_wireable_anchor)crates/socket-patch-cli/src/commands/scan/hosted.rs:2413-2431(see the separate issue on maven redirect confirmation)