Skip to content

Commit 313eec1

Browse files
committed
safe.directory: allow "lead/ing/path/*" match
When safe.directory was introduced in v2.30.3 timeframe, 8959555 (setup_git_directory(): add an owner check for the top-level directory, 2022-03-02), it only allowed specific opt-out directories. Immediately after an embargoed release that included the change, 0f85c4a (setup: opt-out of check with safe.directory=*, 2022-04-13) was done as a response to loosen the check so that a single '*' can be used to say "I trust all repositories" for folks who host too many repositories to list individually. Let's further loosen the check to allow people to say "everything under this hierarchy is deemed safe" by specifying such a leading directory with "/*" appended to it. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 786a3e4 commit 313eec1

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

Documentation/config/safe.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ string `*`. This will allow all repositories to be treated as if their
4444
directory was listed in the `safe.directory` list. If `safe.directory=*`
4545
is set in system config and you want to re-enable this protection, then
4646
initialize your list with an empty value before listing the repositories
47-
that you deem safe.
47+
that you deem safe. Giving a directory with `/*` appended to it will
48+
allow access to all repositories under the named directory.
4849
+
4950
As explained, Git only allows you to access repositories owned by
5051
yourself, i.e. the user who is running Git, by default. When Git

setup.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,13 +1176,21 @@ static int safe_directory_cb(const char *key, const char *value,
11761176
} else if (!strcmp(value, "*")) {
11771177
data->is_safe = 1;
11781178
} else {
1179-
const char *interpolated = NULL;
1180-
1181-
if (!git_config_pathname(&interpolated, key, value) &&
1182-
!fspathcmp(data->path, interpolated ? interpolated : value))
1183-
data->is_safe = 1;
1184-
1185-
free((char *)interpolated);
1179+
const char *allowed = NULL;
1180+
1181+
if (!git_config_pathname(&allowed, key, value)) {
1182+
if (!allowed)
1183+
allowed = value;
1184+
if (ends_with(allowed, "/*")) {
1185+
size_t len = strlen(allowed);
1186+
if (!fspathncmp(allowed, data->path, len - 1))
1187+
data->is_safe = 1;
1188+
} else if (!fspathcmp(data->path, allowed)) {
1189+
data->is_safe = 1;
1190+
}
1191+
}
1192+
if (allowed != value)
1193+
free((char *)allowed);
11861194
}
11871195

11881196
return 0;

t/t0033-safe-directory.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,22 @@ test_expect_success 'safe.directory=*, but is reset' '
7171
expect_rejected_dir
7272
'
7373

74+
test_expect_success 'safe.directory with matching glob' '
75+
git config --global --unset-all safe.directory &&
76+
p=$(pwd) &&
77+
git config --global safe.directory "${p%/*}/*" &&
78+
git status
79+
'
80+
81+
test_expect_success 'safe.directory with unmatching glob' '
82+
git config --global --unset-all safe.directory &&
83+
p=$(pwd) &&
84+
git config --global safe.directory "${p%/*}no/*" &&
85+
expect_rejected_dir
86+
'
87+
7488
test_expect_success 'safe.directory in included file' '
89+
git config --global --unset-all safe.directory &&
7590
cat >gitconfig-include <<-EOF &&
7691
[safe]
7792
directory = "$(pwd)"

0 commit comments

Comments
 (0)