You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The more I look at commit 03c947d the more questions it raises:
it removes repositories from profiles. Why? And what happens with repositories defined in POM itself? Why not removing both, why only one (profile)? What differentiates them from POM defined repositories? And IMHO not removing reposes is the proper solution.
Maven relies on POM defined repositories (they may come from profile), as there is pattern that project -> dep1 -> dep2 where dep1 knows dep2 is not on Central but is somewhere else.
Good questions — worth pinning down, because there are actually two separate axes in 03c947d8 that got entangled:
1 · Profile activation in resolved models. Suppressing property/file-activated profiles in a repository-resolved POM is what broke RESTEasy (#13084): its BOM is imported by a default-on negated-property profile (!resteasy.dependencies.eap) that got filtered out → missing managed versions. #13095 narrows that to re-allow the negated (default-on, non-injectable) case. That's the activation axis.
2 · Repository stripping — the axis you're raising, and I agree it deserves its own scrutiny.
On "why profiles only, not POM-body repos?": as I read it, in a resolved model profiles are activated against the consumer's environment (-D, files, JDK), which is meaningless for a published artifact — so a profile the publisher meant to be inactive can fire in my build and inject its repository. POM-body repos are unconditional (always present, part of the artifact's declared identity), so they stay honored — which is exactly why the project → dep1 → dep2 pattern (dep1 declaring dep2's non-Central repo) keeps working as long as the repo is in the POM body.
But your point stands: if dep1 declares that repo inside a profile (activeByDefault, or a negated default-on profile), the blanket strip breaks it — legitimate functionality lost to a coarse rule.
Your redefine-centric framing is the better-targeted model:
Honor declared repositories (body and legitimately-active profiles).
Scrutinize redefinition of an already-known repository (especially central) — that's the actual attack (silent redirect to a malicious mirror), independent of whether the declaration sits in a profile or the body.
Net: I'd keep #13095 (it fixes the acute activation regression within today's model) and treat this issue as the follow-up that reconsiders the repository axis properly — replacing "strip all profile repos" with "detect + warn/fail on repository redefinition." Happy to help shape that.
One more data point for the record, from a side thread with @cstamas: a fully legitimate pattern is two alternating profiles — e.g. public vs inhouse, each declaring its own <repositories> (inhouse → an MRM). A blanket "strip all profile repositories" breaks exactly that.
Scoping nuance so we're precise: this only bites when such profiles live in a repository-resolved POM (a dependency's own, built at CONSUMER_DEPENDENCY); a consumer's own project/settings profiles are fully evaluated and unaffected. So the problem space is specifically "repositories a dependency contributes via a profile".
For what it's worth, your redefine-detection framing — honor declared repos, scrutinize redefinition of an existing repository (especially central), warn/fail — looks like the right axis to me (cf. #428). Leaving the shape to you.
For the record: the activation axis (#13084) has a fix in progress at #13112 that takes the principled approach — sandbox the ProfileActivationContext rather than filter by activation type.
JDK / OS / activeByDefault → preserved (always correct)
This supersedes #13095. It will need a backport to maven-3.10.x.
The repository-stripping axis (your original concern, and the new comment about alternating public/inhouse profiles each declaring their own repositories) is a separate question that #13112 deliberately doesn't touch. The redefine-detection framing — honor declared repos, warn/fail on redefinition of existing ones (especially central) — looks like the right approach. That's a separate PR/discussion when the design is settled.
The withoutRepositories() / .map() stripping was applied to all active profiles unconditionally — regardless of why they activated. But #13114 already introduced a sandboxed activation context that suppresses consumer -D flags and file conditions before profiles even reach the injection step. The blanket strip was therefore over-broad: it discarded repositories from legitimately-active profiles (JDK/OS, activeByDefault, POM-declared properties) with no security benefit.
The fix removes the stripping for the externalOrigin / VALIDATION_LEVEL_MINIMAL branch in both the compat stack (DefaultModelBuilder.withoutRepositories()) and the impl stack (getActiveProfiles() stripping). The BUILD_CONSUMER stripping (consumer POMs must not leak profile repositories into the published artifact) is unchanged.
This restores the pattern raised in this issue: project → dep1 → dep2 where dep1 declares dep2's repository inside an activeByDefault or JDK-activated profile.
The redefinition concern (a dependency shadowing central with a different URL) is orthogonal and not addressed here — that is a separate WARN/FAIL policy discussion, cf. #428.
Activity
ascheman commentedon Sep 13, 2026
Good questions — worth pinning down, because there are actually two separate axes in
03c947d8that got entangled:1 · Profile activation in resolved models. Suppressing property/file-activated profiles in a repository-resolved POM is what broke RESTEasy (#13084): its BOM is imported by a default-on negated-property profile (
!resteasy.dependencies.eap) that got filtered out → missing managed versions. #13095 narrows that to re-allow the negated (default-on, non-injectable) case. That's the activation axis.2 · Repository stripping — the axis you're raising, and I agree it deserves its own scrutiny.
On "why profiles only, not POM-body repos?": as I read it, in a resolved model profiles are activated against the consumer's environment (
-D, files, JDK), which is meaningless for a published artifact — so a profile the publisher meant to be inactive can fire in my build and inject its repository. POM-body repos are unconditional (always present, part of the artifact's declared identity), so they stay honored — which is exactly why theproject → dep1 → dep2pattern (dep1 declaring dep2's non-Central repo) keeps working as long as the repo is in the POM body.But your point stands: if dep1 declares that repo inside a profile (activeByDefault, or a negated default-on profile), the blanket strip breaks it — legitimate functionality lost to a coarse rule.
Your redefine-centric framing is the better-targeted model:
central) — that's the actual attack (silent redirect to a malicious mirror), independent of whether the declaration sits in a profile or the body.Net: I'd keep #13095 (it fixes the acute activation regression within today's model) and treat this issue as the follow-up that reconsiders the repository axis properly — replacing "strip all profile repos" with "detect + warn/fail on repository redefinition." Happy to help shape that.
ascheman commentedon Sep 14, 2026
One more data point for the record, from a side thread with @cstamas: a fully legitimate pattern is two alternating profiles — e.g.
publicvsinhouse, each declaring its own<repositories>(inhouse → an MRM). A blanket "strip all profile repositories" breaks exactly that.Scoping nuance so we're precise: this only bites when such profiles live in a repository-resolved POM (a dependency's own, built at
CONSUMER_DEPENDENCY); a consumer's own project/settings profiles are fully evaluated and unaffected. So the problem space is specifically "repositories a dependency contributes via a profile".For what it's worth, your redefine-detection framing — honor declared repos, scrutinize redefinition of an existing repository (especially
central), warn/fail — looks like the right axis to me (cf. #428). Leaving the shape to you.gnodet commentedon Sep 14, 2026
For the record: the activation axis (#13084) has a fix in progress at #13112 that takes the principled approach — sandbox the
ProfileActivationContextrather than filter by activation type.The short version of what #13112 does:
-Dflags) → suppressed (consumer didn't set those for the dependency)java.version,os.name, …) → preserved (platform facts)<properties>activation → preserved (part of the artifact's published identity — this is the case Fix #13084: allow negated-property profiles in external model builds #13095 missed)activeByDefault→ preserved (always correct)This supersedes #13095. It will need a backport to
maven-3.10.x.The repository-stripping axis (your original concern, and the new comment about alternating
public/inhouseprofiles each declaring their own repositories) is a separate question that #13112 deliberately doesn't touch. The redefine-detection framing — honor declared repos, warn/fail on redefinition of existing ones (especiallycentral) — looks like the right approach. That's a separate PR/discussion when the design is settled.gnodet commentedon Sep 15, 2026
For the record: the repository-stripping axis (this issue) has a fix in progress at #13116 on the
maven-3.10.xbranch.What #13116 does:
The
withoutRepositories()/.map()stripping was applied to all active profiles unconditionally — regardless of why they activated. But #13114 already introduced a sandboxed activation context that suppresses consumer-Dflags and file conditions before profiles even reach the injection step. The blanket strip was therefore over-broad: it discarded repositories from legitimately-active profiles (JDK/OS,activeByDefault, POM-declared properties) with no security benefit.The fix removes the stripping for the
externalOrigin/VALIDATION_LEVEL_MINIMALbranch in both the compat stack (DefaultModelBuilder.withoutRepositories()) and the impl stack (getActiveProfiles()stripping). TheBUILD_CONSUMERstripping (consumer POMs must not leak profile repositories into the published artifact) is unchanged.This restores the pattern raised in this issue:
project → dep1 → dep2wheredep1declaresdep2's repository inside anactiveByDefaultor JDK-activated profile.The redefinition concern (a dependency shadowing
centralwith a different URL) is orthogonal and not addressed here — that is a separate WARN/FAIL policy discussion, cf. #428.Fix apache#13100: honor repositories from legitimately-active externa…
Fix apache#13100: honor repositories from legitimately-active externa…
Fix #13100: honor repositories from legitimately-active external mode…
Fix apache#13100: honor repositories from legitimately-active externa…
Merge upstream/maven-3.10.x: reconcile with apache#13100 (honor profi…
Merge origin/master: adopt apache#13100 repo-honoring into sandbox ap…
Fix #13100: honor repositories from legitimately-active external mode…