Resolver 2.0.23-SNAPSHOT and validation cleanup - #13078
Conversation
We had overlapping changes in Resolver and Maven, align them.
|
Sure about the SNAPSHOT-dependency, @cstamas ? Or will you resolve this before you make the draft final? |
|
We usually run "main" branches (in quotes, as we have several "main" branches, the master, the maven-4.0.x, the maven-3.10.x, etc) just before the release with SNAPSHOT versions, as we do produce and deploy them, is fine to get another layer of confirmation. OTOH, you cannot release anyway with a SNAPSHOT, hence, this is completely okay, and we did it before as well. |
|
So, all of ITs explode, reason is f013 in this commit: @gnodet ping |
|
@cstamas The root cause is the tracking key function change from This affects all 9 IT jobs (4229 test failures, 507 unique test classes on ubuntu/JDK26 alone). The Fix PR: apache/maven-resolver#2133 — adds a backward-compatible fallback in |
…allback (#2133) ## Summary When the tracking key function is URL-qualified (`nid_hurl`, the default since 2.0.23 / commit 339161b), tracking entries written by an older resolver using ID-only keys (`nid` format, e.g. `artifact>central=`) are invisible to the new lookup which expects `artifact>central-<sha1>=`. This causes **all** artifacts cached in the local repository before the upgrade to appear as "present but unavailable", triggering full re-downloads from remote repositories. In CI environments and integration tests that use fake/file-based repositories (like maven-integration-testing), this breaks resolution entirely — see [apache/maven#13078 (comment)](apache/maven#13078 (comment)). ## Root Cause The tracking key change from `nid` to `nid_hurl` (finding f013 in the security audit) makes existing `_remote.repositories` entries invisible: - **Old entry**: `maven-core-3.8.6.pom>central=` - **New lookup**: `maven-core-3.8.6.pom>central-<sha1 of repo URL>=` → no match The `isTracked()` check finds the old `central=` entry, so the artifact is treated as "tracked but not for the current repo" rather than "untracked" — the untracked inter-op fallback does not apply, and the artifact is rejected. ## Fix Add a backward-compatible fallback in `applyTracking()`: when the URL-qualified (`nid_hurl`) lookup misses, try the system-wide key function (`nid` by default) as a fallback. If that matches, accept the artifact and log a debug message. The legacy entry will be upgraded to the new key format on the next download. This preserves the f013 security improvement (URL-qualified tracking prevents same-id-different-URL repository poisoning for *new* entries) while providing a smooth upgrade path from older resolvers. ## Tests - Updated `testUrlQualifiedTrackingTreatsLegacyIdOnlyEntriesAsStale` → `testUrlQualifiedTrackingAcceptsLegacyIdOnlyEntriesViaFallback`: legacy entries from a matching repo are now accepted - Added `testUrlQualifiedTrackingRejectsLegacyIdOnlyEntriesFromDifferentRepo`: legacy entries from a *different* repo are still rejected - `testUrlQualifiedTrackingDistinguishesSameIdDifferentUrl`: unchanged — URL-qualified entries still prevent same-id-different-URL poisoning
|
Updated the resolver fix PR based on @cstamas's analysis. The first fix only handled legacy The ITs override The fix now has a two-stage fallback:
This effectively relaxes f013 to recording-only: entries are written with URL-qualified keys, but lookups fall back to repo-ID matching. All 585 resolver tests pass. Fix PR: apache/maven-resolver#2133 (force-pushed with the updated fix) |
|
@cstamas — the SNAPSHOT and IT-explosion questions are resolved on my side (thanks, and to @gnodet for #2133). One code point from the validation consolidation itself, independent of the IT fix: The removed Two minors: |
gnodet
left a comment
There was a problem hiding this comment.
Review: validation consolidation looks correct, one gap to fix
The consolidation from two separate validation sites (DefaultMetadataReader.validateMetadata() and DefaultRepositoryMetadataManager.validateVersioning()) into the single ValidatingMetadataXpp3Reader.validate() is clean — it eliminates the duplicate validateVersioning() call and the now-redundant per-reader validation logic.
The new validate() method correctly covers versioning tokens (latest, release, versions[], snapshotVersions[].version, snapshot.timestamp) and plugin.getArtifactId(). The snapshot timestamp validation and metadata.getVersion() validation are new additions not present in either old reader — good.
However, as @ascheman noted: plugin.getPrefix() validation was dropped. The removed DefaultMetadataReader.validateMetadata() explicitly validated both plugin.getArtifactId() and plugin.getPrefix(), with its Javadoc stating these "get carried forward by callers as if they were already-validated path and coordinate components." The consolidated reader only validates plugin.getArtifactId().
Fix: add PathUtils.validatePathComponent(plugin.getPrefix(), "plugin/prefix"); alongside the artifactId validation in ValidatingMetadataXpp3Reader.validate().
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of @gnodet
| PathUtils.validatePathComponent(metadata.getVersion(), "version"); | ||
| for (Plugin plugin : metadata.getPlugins()) { | ||
| PathUtils.validatePathComponent(plugin.getArtifactId(), "plugin/artifactId"); | ||
| } |
There was a problem hiding this comment.
@ascheman's observation is correct — plugin.getPrefix() validation was present in the removed DefaultMetadataReader.validateMetadata() but was not carried over here. Since prefixes are used as coordinate/path components downstream, this should be:
| } | |
| PathUtils.validatePathComponent(plugin.getArtifactId(), "plugin/artifactId"); | |
| PathUtils.validatePathComponent(plugin.getPrefix(), "plugin/prefix"); |
We had overlapping changes in Resolver and Maven, align them.