Skip to content

Issue #13265: let a settings server declare the repository origins its credentials may be used with - #13268

Open
slawekjaranowski wants to merge 1 commit into
apache:masterfrom
slawekjaranowski:issue-13265-server-repository-origins
Open

slawekjaranowski wants to merge 1 commit into
apache:masterfrom
slawekjaranowski:issue-13265-server-repository-origins

Conversation

@slawekjaranowski

Copy link
Copy Markdown
Member

Problem

Credentials of a <server> are bound to the origin (scheme, host, port) of the repositories and mirrors declared with the same id (maven.repository.credentialScope, default origin). declaredRepositoryOrigins is built in DefaultRepositorySystemSessionFactory from the mirrors and from request.getRemoteRepositories() / getPluginArtifactRepositories().

Repositories declared inside a settings.xml <profile> only reach those lists when the profile id is listed in <settings><activeProfiles>. A profile activated through <activation> (property, jdk, os, file) or through -P contributes no origin at all, so a perfectly legitimate corporate repository gets:

  • under the default origin scope: a warning on every build, with no way to silence it;
  • under strict: refused credentials and a 401.

This cannot be fixed automatically: the repository system session is created before any project is read, and profile activation is resolved later, per project, by the model builder.

Solution

A <server> can declare the origins its credentials may be used with:

<server>
  <id>internal</id>
  <username>u</username>
  <password>p</password>
  <repositoryOrigins>
    <repositoryOrigin>https://repo.example.org</repositoryOrigin>
    <repositoryOrigin>https://mirror.example.org:8443</repositoryOrigin>
  </repositoryOrigins>
</server>
  • Union, not replacement — declared origins are added to the ones Maven discovers itself, so existing configurations are unaffected.
  • Bare origins, not repository URLs. They go through the same normalization as every other origin: case-insensitive, :80/:443 equivalent to no port. Values are checked by settings validation, so a typo is reported where it is written rather than surfacing later as a refused credential.
  • The warnings emitted by the origin binding now name <repositoryOrigins> as the place to declare a missing origin, so the message is actionable.

Project settings

<repositoryOrigins> is dropped from project settings (.mvn/settings.xml) and warned about, exactly like credentials are. This is a security requirement: settings list fields merge by union, and a project-settings <server> with the same id survives as a separate entry of the servers list, which the session factory reads too. Without the scrub, a project could widen the set of hosts its user's credentials are sent to. DefaultSettingsParserTest#projectSettingsCannotWidenServerCredentialOrigins fails without it.

🤖 Generated with Claude Code

…ins its credentials may be used with

Server credentials are scoped to the origin (scheme, host and port) of the
repositories and mirrors declared with the same server id. Repositories
declared inside a settings profile only reach that set when the profile id is
listed in <activeProfiles>; a profile activated through <activation> or -P
contributes no origin, so its credentials are warned about under the default
origin scope and refused under strict, with nothing the operator can do about
it. The session is built before any project exists, so profile activation
cannot be evaluated there.

A <server> can now declare those origins explicitly:

  <server>
    <id>internal</id>
    <username>u</username>
    <password>p</password>
    <repositoryOrigins>
      <repositoryOrigin>https://repo.example.org</repositoryOrigin>
      <repositoryOrigin>https://mirror.example.org:8443</repositoryOrigin>
    </repositoryOrigins>
  </server>

The declared origins are added to the ones Maven derives on its own; nothing
is replaced. Values are bare origins, not repository URLs, and are validated:
a value no origin can be derived from is an error, while a full repository URL
is accepted with a warning naming the origin actually used. The deprecated V3
validator skips values with a property placeholder, as it runs before
interpolation.

The element is dropped from project settings, like credentials are. This is a
security requirement rather than tidiness: settings list fields merge by union
and a project-settings <server> of the same id survives as a separate entry, so
without it a project could widen the origins its user's credentials are sent
to.

The warnings of the origin binding now name <repositoryOrigins> as the way to
declare a missing origin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@slawekjaranowski slawekjaranowski added the bug Something isn't working label Sep 24, 2026
@slawekjaranowski slawekjaranowski linked an issue Sep 24, 2026 that may be closed by this pull request
@slawekjaranowski slawekjaranowski self-assigned this Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sort out credentials scope handling

1 participant