Subject: [PATCH 00/16] Auto-configure advertised remotes via URL whitelist

From: Christian Couder <[email-masked]>
Date: Mon, 23 Mar 2026 09:05:03 +0100

Currently, the "promisor-remote" protocol capability allows a server
to advertise promisor remotes (and their tokens/filters), but the
client's `promisor.acceptFromServer` mechanism requires these remotes
to already exist in the config.

This is a significant burden for users and administrators who have to
pre-configure remotes.

This patch series improves on this by introducing a new
`promisor.acceptFromServerUrl` config option, which provides an
additive, URL-based security whitelist.

Multiple `promisor.acceptFromServerUrl` config options can be provided
in different config files. Each one should contain a URL glob pattern
which can optionally be prefixed with a remote name in the
"[<name>=]<pattern>" format.

With this new config option:

 - The server can update fields (like tokens) for known remotes,
   provided their URL matches the whitelist, even if
   `acceptFromServer` is set to `None`.

 - Unknown remotes advertised by the server can be automatically
   configured on the client if their URL matches the whitelist.

 - If there is no `<name>` prefix before the glob pattern matched, the
   auto-configured remote is named using the
   "promisor-auto-<sanitized-url>" format. So the same auto-configured
   remote config entry will be reused for the same URL.

 - If a `<name>` prefix is provided, it will be used for the
   auto-configured remote config entry.

 - If the chosen name (auto-generated or prefixed) already exists but
   points to a different URL, overwriting the existing config is
   prevented by appending a numeric suffix (e.g., -1, -2) to the name
   and auto-configuring using that name.

 - The server's originally advertised name is always saved in the
   `remote.<name>.advertisedAs` config variable of the auto-configured
   remote for tracing and debugging.

 - To honor the server's recommendation, promisor_remote_get_direct()
   is updated to try accepted remotes first before falling back to
   other configured promisor remotes. This ensures auto-configured
   remotes are preferred over other remotes especially the
   partial-clone origin.

Security considerations:

 - Advertised URLs are routed through url_normalize() before matching
   against the user's glob patterns to prevent percent-encoding, case
   variation, or path-traversal (../) bypasses.

 - Auto-generated remote names are sanitized (non-alphanumeric
   characters are replaced with '-' and prefixed with
   'promisor-auto-'). This guarantees safe config section names and
   prevents a server from maliciously overwriting standard remotes
   (like origin).

 - The documentation explains in detail how to use secure glob
   patterns in `promisor.acceptFromServerUrl`.

High level description of the patches
=====================================

 - Patch 1/16 ("promisor-remote: try accepted remotes before others in
   get_direct()"):

   Fixes promisor_remote_get_direct() to prioritize accepted
   remotes. This could be a separate fix, but is needed towards the
   end of the series.

 - Patches 2-3/16 ("urlmatch:*"):

   Exposes and adapts helpers in the urlmatch API.

 - Patches 4-11/16 ("promisor-remote:*"):

   Big refactoring of filter_promisor_remote() and
   should_accept_remote(). This keeps `struct promisor_info` instances
   alive longer to anticipate possible state-desync bugs, decouples
   the server's advertised name from the local config name, and
   sanitizes control flow without changing the existing behavior.

 - Patch 12/16 ("t5710:*"):

   Cleans up how "file://" URIs are managed in the test script to
   prepare for URI normalization later in the series and avoid issues
   on Windows.

 - Patches 13-15/16 ("promisor-remote:*"):

   The core feature. Introduces the parsing machinery, adds the
   additive whitelist for known remotes (with url_normalize()
   security), and finally implements the auto-creation and collision
   resolution for unknown remotes.

 - Patch 16/16 ("doc: promisor: improve acceptFromServer entry"):

   Cleans up and modernizes the existing `promisor.acceptFromServer`
   documentation.

CI tests
========

They all pass, see:

https://github.com/chriscool/git/actions/runs/23350745268

Christian Couder (16):
  promisor-remote: try accepted remotes before others in get_direct()
  urlmatch: change 'allow_globs' arg to bool
  urlmatch: add url_is_valid_pattern() helper
  promisor-remote: clarify that a remote is ignored
  promisor-remote: refactor has_control_char()
  promisor-remote: refactor accept_from_server()
  promisor-remote: keep accepted promisor_info structs alive
  promisor-remote: remove the 'accepted' strvec
  promisor-remote: add 'local_name' to 'struct promisor_info'
  promisor-remote: pass config entry to all_fields_match() directly
  promisor-remote: refactor should_accept_remote() control flow
  t5710: use proper file:// URIs for absolute paths
  promisor-remote: introduce promisor.acceptFromServerUrl
  promisor-remote: trust known remotes matching acceptFromServerUrl
  promisor-remote: auto-configure unknown remotes
  doc: promisor: improve acceptFromServer entry

 Documentation/config/promisor.adoc    | 118 +++++-
 Documentation/config/remote.adoc      |   9 +
 Documentation/gitprotocol-v2.adoc     |   9 +-
 promisor-remote.c                     | 532 +++++++++++++++++++++-----
 t/t5710-promisor-remote-capability.sh | 250 ++++++++++--
 urlmatch.c                            |  18 +-
 urlmatch.h                            |  11 +
 7 files changed, 802 insertions(+), 145 deletions(-)

-- 
2.53.0.625.g20f70b52bb