Skip to content

Commit b0cd667

Browse files
committed
Merge branch 'cc/promisor-auto-config-url' into jch
Promisor remote handling is enhanced to auto-configure remotes based on a URL whitelist. * cc/promisor-auto-config-url: doc: promisor: improve acceptFromServer entry promisor-remote: auto-configure unknown remotes promisor-remote: trust known remotes matching acceptFromServerUrl promisor-remote: introduce promisor.acceptFromServerUrl t5710: use proper file:// URIs for absolute paths promisor-remote: refactor should_accept_remote() control flow promisor-remote: pass config entry to all_fields_match() directly promisor-remote: add 'local_name' to 'struct promisor_info' promisor-remote: remove the 'accepted' strvec promisor-remote: keep accepted promisor_info structs alive promisor-remote: refactor accept_from_server() promisor-remote: refactor has_control_char() promisor-remote: clarify that a remote is ignored urlmatch: add url_is_valid_pattern() helper urlmatch: change 'allow_globs' arg to bool promisor-remote: try accepted remotes before others in get_direct()
2 parents 6237a33 + d92889e commit b0cd667

7 files changed

Lines changed: 802 additions & 145 deletions

File tree

Documentation/config/promisor.adoc

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,106 @@ variable is set to "true", and the "name" and "url" fields are always
3232
advertised regardless of this setting.
3333

3434
promisor.acceptFromServer::
35-
If set to "all", a client will accept all the promisor remotes
36-
a server might advertise using the "promisor-remote"
37-
capability. If set to "knownName" the client will accept
38-
promisor remotes which are already configured on the client
39-
and have the same name as those advertised by the client. This
40-
is not very secure, but could be used in a corporate setup
41-
where servers and clients are trusted to not switch name and
42-
URLs. If set to "knownUrl", the client will accept promisor
43-
remotes which have both the same name and the same URL
44-
configured on the client as the name and URL advertised by the
45-
server. This is more secure than "all" or "knownName", so it
46-
should be used if possible instead of those options. Default
47-
is "none", which means no promisor remote advertised by a
48-
server will be accepted. By accepting a promisor remote, the
49-
client agrees that the server might omit objects that are
50-
lazily fetchable from this promisor remote from its responses
51-
to "fetch" and "clone" requests from the client. Name and URL
52-
comparisons are case sensitive. See linkgit:gitprotocol-v2[5].
35+
Controls which promisor remotes advertised by a server (using the
36+
"promisor-remote" protocol capability) a client will accept. By
37+
accepting a promisor remote, the client agrees that the server
38+
might omit objects that are lazily fetchable from this promisor
39+
remote from its responses to "fetch" and "clone" requests.
40+
+
41+
Note that this option does not cause new remotes to be automatically
42+
created in the client's configuration. It only allows remotes which
43+
are somehow already configured to be trusted for the current
44+
operation, or their fields to be updated (if `promisor.storeFields` is
45+
set and the remote already exists locally). To allow Git to
46+
automatically create and persist new remotes from server
47+
advertisements, use `promisor.acceptFromServerUrl`.
48+
+
49+
The available options are:
50+
+
51+
* `none` (default): No promisor remote advertised by a server will be
52+
accepted.
53+
+
54+
* `knownUrl`: The client will accept promisor remotes that are already
55+
configured on the client and have both the same name and the same URL
56+
as advertised by the server. This is more secure than `all` or
57+
`knownName`, and should be used if possible instead of those options.
58+
+
59+
* `knownName`: The client will accept promisor remotes that are already
60+
configured on the client and have the same name as those advertised
61+
by the server. This is not very secure, but could be used in a corporate
62+
setup where servers and clients are trusted to not switch names and URLs.
63+
+
64+
* `all`: The client will accept all the promisor remotes a server might
65+
advertise. This is the least secure option and should only be used in
66+
fully trusted environments.
67+
+
68+
Name and URL comparisons are case-sensitive. See linkgit:gitprotocol-v2[5]
69+
for protocol details.
70+
71+
promisor.acceptFromServerUrl::
72+
A glob pattern to specify which URLs advertised by a server
73+
are allowed to be auto-configured (created and persisted) on
74+
the client side. Unlike `promisor.acceptFromServer`, which
75+
only accepts already configured remotes, a match against this
76+
option instructs Git to write a new `[remote "<name>"]`
77+
section to the client's configuration.
78+
+
79+
This option can appear multiple times in config files. An advertised
80+
URL will be accepted if it matches _ANY_ glob pattern specified by
81+
this option in _ANY_ config file read by Git.
82+
+
83+
Be _VERY_ careful with these glob patterns, as it can be a big
84+
security hole to allow any advertised remote to be auto-configured!
85+
To minimize security risks, follow these guidelines:
86+
+
87+
1. Start with a secure protocol scheme, like `https://` or `ssh://`.
88+
+
89+
2. Only allow domain names or paths where you control and trust _ALL_
90+
the content. Be especially careful with shared hosting platforms
91+
like `github.com` or `gitlab.com`. A broad pattern like
92+
`https://gitlab.com/*` is dangerous because it trusts every
93+
repository on the entire platform. Always restrict such patterns to
94+
your specific organization or namespace (e.g.,
95+
`https://gitlab.com/your-org/*`).
96+
+
97+
3. Don't use globs (`*`) in the domain name. For example
98+
`https://cdn.example.com/*` is much safer than
99+
`https://*.example.com/*`, because the latter matches
100+
`https://evil-hacker.net/fake.example.com/repo`.
101+
+
102+
4. Make sure to have a `/` at the end of the domain name (or the end
103+
of specific directories). For example `https://cdn.example.com/*`
104+
is much safer than `https://cdn.example.com*`, because the latter
105+
matches `https://cdn.example.com.hacker.net/repo`.
106+
+
107+
Before matching, the advertised URL is normalized: the scheme and
108+
host are lowercased, percent-encoded characters are decoded where
109+
possible, and path segments like `..` are resolved. Glob patterns
110+
are matched against this normalized URL as-is, so patterns should
111+
be written in normalized form (e.g., lowercase scheme and host).
112+
+
113+
The glob pattern can optionally be prefixed with a remote name and an
114+
equals sign (e.g., `cdn=https://cdn.example.com/*`). If such a prefix
115+
is provided, accepted remotes will be saved under that name. If no
116+
such prefix is provided, a safe remote name will be automatically
117+
generated by sanitizing the URL and prefixing it with
118+
`promisor-auto-`. If a remote with the chosen name already exists but
119+
points to a different URL, Git will append a numeric suffix (e.g.,
120+
`-1`, `-2`) to the name to prevent overwriting existing
121+
configurations. You should make sure that this doesn't happen often
122+
though, as remotes will be rejected if the numeric suffix increases
123+
too much. In all cases, the original name advertised by the server is
124+
recorded in the `remote.<name>.advertisedAs` configuration variable
125+
for tracing and debugging purposes.
126+
+
127+
Note that this option acts as an additive security whitelist. It works
128+
in conjunction with `promisor.acceptFromServer` (see the documentation
129+
of that option for the implications of accepting a promisor
130+
remote). Even if `promisor.acceptFromServer` is set to `None` (the
131+
default), Git will still automatically configure new remotes, and
132+
accept field updates (like tokens) for known remotes, provided their
133+
URLs match a pattern in `promisor.acceptFromServerUrl`. See
134+
linkgit:gitprotocol-v2[5] for details on the protocol.
53135

54136
promisor.checkFields::
55137
A comma or space separated list of additional remote related

Documentation/config/remote.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ remote.<name>.promisor::
9191
When set to true, this remote will be used to fetch promisor
9292
objects.
9393

94+
remote.<name>.advertisedAs::
95+
When a promisor remote is automatically configured using
96+
information advertised by a server through the
97+
`promisor-remote` protocol capability (see
98+
`promisor.acceptFromServerUrl`), the server's originally
99+
advertised name is saved in this variable. This is for
100+
information, tracing and debugging purposes. Users should not
101+
typically modify or create such configuration entries.
102+
94103
remote.<name>.partialclonefilter::
95104
The filter that will be applied when fetching from this promisor remote.
96105
Changing or clearing this value will only affect fetches for new commits.

Documentation/gitprotocol-v2.adoc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -862,10 +862,11 @@ the server advertised, the client shouldn't advertise the
862862
863863
On the server side, the "promisor.advertise" and "promisor.sendFields"
864864
configuration options can be used to control what it advertises. On
865-
the client side, the "promisor.acceptFromServer" configuration option
866-
can be used to control what it accepts, and the "promisor.storeFields"
867-
option, to control what it stores. See the documentation of these
868-
configuration options in linkgit:git-config[1] for more information.
865+
the client side, the "promisor.acceptFromServer" and
866+
"promisor.acceptFromServerUrl" configuration options can be used to
867+
control what it accepts, and the "promisor.storeFields" option, to
868+
control what it stores. See the documentation of these configuration
869+
options in linkgit:git-config[1] for more information.
869870
870871
Note that in the future it would be nice if the "promisor-remote"
871872
protocol capability could be used by the server, when responding to

0 commit comments

Comments
 (0)