diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.txt index 577df40223a095..2d45c98b12d951 100644 --- a/Documentation/config/safe.txt +++ b/Documentation/config/safe.txt @@ -44,7 +44,8 @@ string `*`. This will allow all repositories to be treated as if their directory was listed in the `safe.directory` list. If `safe.directory=*` is set in system config and you want to re-enable this protection, then initialize your list with an empty value before listing the repositories -that you deem safe. +that you deem safe. Giving a directory with `/*` appended to it will +allow access to all repositories under the named directory. + As explained, Git only allows you to access repositories owned by yourself, i.e. the user who is running Git, by default. When Git diff --git a/setup.c b/setup.c index 15abbaf21a758c..8a5242184b501a 100644 --- a/setup.c +++ b/setup.c @@ -1177,13 +1177,21 @@ static int safe_directory_cb(const char *key, const char *value, } else if (!strcmp(value, "*")) { data->is_safe = 1; } else { - const char *interpolated = NULL; - - if (!git_config_pathname(&interpolated, key, value) && - !fspathcmp(data->path, interpolated ? interpolated : value)) - data->is_safe = 1; - - free((char *)interpolated); + const char *allowed = NULL; + + if (!git_config_pathname(&allowed, key, value)) { + if (!allowed) + allowed = value; + if (ends_with(allowed, "/*")) { + size_t len = strlen(allowed); + if (!fspathncmp(allowed, data->path, len - 1)) + data->is_safe = 1; + } else if (!fspathcmp(data->path, allowed)) { + data->is_safe = 1; + } + } + if (allowed != value) + free((char *)allowed); } return 0; diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh index 11c3e8f28e0df9..5fe61f129129ef 100755 --- a/t/t0033-safe-directory.sh +++ b/t/t0033-safe-directory.sh @@ -71,7 +71,22 @@ test_expect_success 'safe.directory=*, but is reset' ' expect_rejected_dir ' +test_expect_success 'safe.directory with matching glob' ' + git config --global --unset-all safe.directory && + p=$(pwd) && + git config --global safe.directory "${p%/*}/*" && + git status +' + +test_expect_success 'safe.directory with unmatching glob' ' + git config --global --unset-all safe.directory && + p=$(pwd) && + git config --global safe.directory "${p%/*}no/*" && + expect_rejected_dir +' + test_expect_success 'safe.directory in included file' ' + git config --global --unset-all safe.directory && cat >gitconfig-include <<-EOF && [safe] directory = "$(pwd)"