Validate metadata inputs and honour checksum policy on legacy paths - #13002
Conversation
…policy Backport of the path traversal validation and checksum policy fixes from #12950 (master) / #12945 (maven-4.0.x) / #12978 (maven-3.10.x) to the maven-3.9.x branch. - Path traversal: AbstractRepositoryMetadata.getLocalFilename() and LegacyLocalRepositoryManager.ArtifactMetadataAdapter.getLocalFilename() now reject repository keys containing '..', '/', '\', ':', or ISO control characters. - Metadata token validation: DefaultRepositoryMetadataManager.readMetadata() validates every version token (latest, release, versions, snapshot versions, snapshot timestamp) for the same characters after parsing. - Checksum policy: resolve() now catches ChecksumFailedException separately and fails metadata resolution under checksumPolicy=fail. getArtifactMetadataFromDeploymentRepository() and LegacyRepositorySystem.retrieve() resolve the effective policy from the repository configuration instead of hardcoding 'warn'. The proxy clone fix (DefaultSettingsDecrypter) is not included because 3.9.x already clones each proxy before decryption. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet
left a comment
There was a problem hiding this comment.
Clean, faithful backport of security hardening (path traversal validation and checksum policy enforcement) to the maven-3.9.x legacy compat layer. All adaptations for the 3.9.x module structure are correct; no logic drift from the source PRs.
Two low-severity observations (both already noted in the upstream #12945 review):
-
Code duplication —
isInvalidPathToken/validateRepositoryKeyare duplicated verbatim betweenAbstractRepositoryMetadata(maven-core) andLegacyLocalRepositoryManager.ArtifactMetadataAdapter(maven-core). Both are in the same module and could share a package-private utility. Acceptable for deprecated compat code and consistent with the upstream PRs. -
Update tracker inconsistency on deployment path —
getArtifactMetadataFromDeploymentRepositorystill touches the update tracker in itsfinallyblock, meaning aChecksumFailedException(now possible with the newly configurable policy) will mark the metadata as checked and suppress retry for the full update interval. This contrasts withresolve()which deliberately skips the touch on checksum failure. Low severity because the deployment path is not retry-sensitive in the same way as resolution.
📋 PR Metadata
| Aspect | Current | Suggested |
|---|---|---|
| Category | (unlabeled) | bug |
| Labels | (none) | + bug |
| Milestone | (none) | 3.9.17 |
🔀 Backport Status
✅ This PR is the 3.9.x backport. All maintenance branches are covered:
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
Backport of the path traversal validation and checksum policy fixes from #12950 (master) / #12945 (maven-4.0.x) / #12978 (maven-3.10.x) to the
maven-3.9.xbranch.Path traversal validation
AbstractRepositoryMetadata.getLocalFilename()andLegacyLocalRepositoryManager.ArtifactMetadataAdapter.getLocalFilename()now reject a repository key that is.., contains/,\,:, or an ISO control character before using it in a local file name.DefaultRepositoryMetadataManager.readMetadata()validates every version token carried by parsed repository metadata (latest, release, versions, snapshot versions, snapshot timestamp) for the same path traversal characters.Checksum policy enforcement
DefaultRepositoryMetadataManager.resolve()now catchesChecksumFailedExceptionseparately and fails metadata resolution underchecksumPolicy=failinstead of downgrading to a warning. The update-check file is only touched on success, not-found, or generic transfer failure, so checksum failures are retried on the next build.getArtifactMetadataFromDeploymentRepository()resolves the effective policy from the repository configuration instead of hardcodingwarn.LegacyRepositorySystem.retrieve()resolves the effective policy from the repository configuration (stricter of release/snapshot) instead of hardcodingwarn.The proxy clone fix (
DefaultSettingsDecrypter) is not included because 3.9.x already clones each proxy before decryption.Adapted for the 3.9.x module structure (no
compat/prefix,AbstractRepositoryMetadatainmaven-core,MetadataXpp3Readerinstead ofMetadataStaxReader, noinstanceofpattern matching).Test plan
AbstractRepositoryMetadataTest(4 tests): repo keys with/,\,..,:are rejected; well-formed key produces correct filenameLegacyLocalRepositoryManagerTest(3 tests): repo keys with path separators and..are rejected in the inner adapterDefaultRepositoryMetadataManagerValidationTest(2 tests): metadata with invalid version token (colon) and invalid snapshot timestamp (colon) are rejectedDefaultRepositoryMetadataManagerTest(1 test):resolve()throwsRepositoryMetadataResolutionExceptionwhen checksum policy isfailand checksums do not matchLegacyRepositorySystemTest.testRetrieveHonorsConfiguredFailChecksumPolicy:retrieve()throwsArtifactTransferFailedExceptionwhen checksum policy isfailmvn test -pl maven-corepassesmvn test -pl maven-compatpasses🤖 Generated with Claude Code