setup: opt-out of check with safe.directory=*

With the addition of the safe.directory in 8959555ce (setup_git_directory(): add an owner check for the top-level directory, 2022-03-02) released in v2.35.2, we are receiving feedback from a variety of users about the feature. Some users have a very large list of shared repositories and find it cumbersome to add this config for every one of them. In a more difficult case, certain workflows involve running Git commands within containers. The container boundary prevents any global or system config from communicating `safe.directory` values from the host into the container. Further, the container almost always runs as a different user than the owner of the directory in the host. To simplify the reactions necessary for these users, extend the definition of the safe.directory config value to include a possible '*' value. This value implies that all directories are safe, providing a single setting to opt-out of this protection. Note that an empty assignment of safe.directory clears all previous values, and this is already the case with the "if (!value || !*value)" condition. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Apr 13, 2022 at 15:32 UTC 0f85c4a30b072a26d74af8bbf63cc8f6a5dfc1b8
3 files changed +21 -2
Documentation/config/safe.txt
+7
@@ -19,3 +19,10 @@ line option `-c safe.directory=<path>`.
19 The value of this setting is interpolated, i.e. `~/<path>` expands to a
20 path relative to the home directory and `%(prefix)/<path>` expands to a
21 path relative to Git's (runtime) prefix.
22 ++
23 +To completely opt-out of this security check, set `safe.directory` to the
24 +string `*`. This will allow all repositories to be treated as if their
25 +directory was listed in the `safe.directory` list. If `safe.directory=*`
26 +is set in system config and you want to re-enable this protection, then
27 +initialize your list with an empty value before listing the repositories
28 +that you deem safe.
setup.c
+4 -2
@@ -1037,9 +1037,11 @@ static int safe_directory_cb(const char *key, const char *value, void *d)
1037 if (strcmp(key, "safe.directory"))
1038 return 0;
1039
1040 - if (!value || !*value)
1040 + if (!value || !*value) {
1041 data->is_safe = 0;
1042 - else {
1042 + } else if (!strcmp(value, "*")) {
1043 + data->is_safe = 1;
1044 + } else {
1045 const char *interpolated = NULL;
1046
1047 if (!git_config_pathname(&interpolated, key, value) &&
t/t0033-safe-directory.sh
+10
@@ -36,4 +36,14 @@ test_expect_success 'safe.directory matches, but is reset' '
36 expect_rejected_dir
37 '
38
39 +test_expect_success 'safe.directory=*' '
40 + git config --global --add safe.directory "*" &&
41 + git status
42 +'
43 +
44 +test_expect_success 'safe.directory=*, but is reset' '
45 + git config --global --add safe.directory "" &&
46 + expect_rejected_dir
47 +'
48 +
49 test_done