Add configuration option 'core.allowProtocol' to allow users to create a
whitelist of allowed protocols for fetch/push/clone in their gitconfig.

For git-submodule.sh, fallback to default whitelist only if the user
hasn't explicitly set `GIT_ALLOW_PROTOCOL` or doesn't have a whitelist
in their gitconfig.

Signed-off-by: Brandon Williams <bmw...@google.com>
---
 Documentation/config.txt    |  8 ++++++++
 Documentation/git.txt       |  6 ++++--
 git-submodule.sh            |  3 ++-
 t/lib-proto-disable.sh      | 27 +++++++++++++++++++++++++++
 t/t5815-submodule-protos.sh | 22 ++++++++++++++++++++++
 transport.c                 |  6 ++++++
 6 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 27069ac..78c97e3 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -455,6 +455,14 @@ core.sshCommand::
        the `GIT_SSH_COMMAND` environment variable and is overridden
        when the environment variable is set.
 
+core.allowProtocol::
+       Provide a colon-separated list of protocols which are allowed to be
+       used with fetch/push/clone.  Any protocol not mentioned will be
+       disallowed (i.e., this is a whitelist, not a blacklist).  If the
+       `GIT_ALLOW_PROTOCOL` environment variable is set, it is used as the
+       protocol whitelist instead of this config option.  If neither is set,
+       all protocols are enabled. See git(1) for more details.
+
 core.ignoreStat::
        If true, Git will avoid using lstat() calls to detect if files have
        changed by setting the "assume-unchanged" bit for those tracked files
diff --git a/Documentation/git.txt b/Documentation/git.txt
index ab7215e..a86ec16 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -1155,8 +1155,10 @@ of clones and fetches.
        restrict recursive submodule initialization from an untrusted
        repository. Any protocol not mentioned will be disallowed (i.e.,
        this is a whitelist, not a blacklist). If the variable is not
-       set at all, all protocols are enabled.  The protocol names
-       currently used by git are:
+       set at all, all protocols are enabled.  The exception to this is when
+       running `git-submodule` which will use a default list of known-safe
+       protocols (file:git:http:https:ssh) in the event no whitelist is
+       provided.  The protocol names currently used by git are:
 
          - `file`: any local file-based path (including `file://` URLs,
            or local paths)
diff --git a/git-submodule.sh b/git-submodule.sh
index a024a13..bfbfb8e 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -27,7 +27,8 @@ cd_to_toplevel
 #
 # If the user has already specified a set of allowed protocols,
 # we assume they know what they're doing and use that instead.
-: ${GIT_ALLOW_PROTOCOL=file:git:http:https:ssh}
+whitelist=$(git config core.allowProtocol) || whitelist=file:git:http:https:ssh
+: ${GIT_ALLOW_PROTOCOL=$whitelist}
 export GIT_ALLOW_PROTOCOL
 
 command=
diff --git a/t/lib-proto-disable.sh b/t/lib-proto-disable.sh
index b0917d9..e8820a6 100644
--- a/t/lib-proto-disable.sh
+++ b/t/lib-proto-disable.sh
@@ -62,6 +62,33 @@ test_proto () {
                        test_must_fail git clone --bare "$url" tmp.git
                )
        '
+
+       # Run tests again using the gitconfig method for setting a whitelist
+       test_expect_success "clone $1 (enabled)" '
+               rm -rf tmp.git &&
+               git -c core.allowProtocol="$proto" clone --bare "$url" tmp.git
+       '
+
+       test_expect_success "fetch $1 (enabled)" '
+               git -C tmp.git -c core.allowProtocol="$proto" fetch
+       '
+
+       test_expect_success "push $1 (enabled)" '
+               git -C tmp.git -c core.allowProtocol="$proto" push origin 
HEAD:pushed
+       '
+
+       test_expect_success "push $1 (disabled)" '
+               test_must_fail git -C tmp.git -c core.allowProtocol=none push 
origin HEAD:pushed
+       '
+
+       test_expect_success "fetch $1 (disabled)" '
+               test_must_fail git -C tmp.git -c core.allowProtocol=none fetch
+       '
+
+       test_expect_success "clone $1 (disabled)" '
+               rm -rf tmp.git &&
+               test_must_fail git -C tmp.git -c core.allowProtocol=none clone 
--bare "$url" tmp.git
+       '
 }
 
 # set up an ssh wrapper that will access $host/$repo in the
diff --git a/t/t5815-submodule-protos.sh b/t/t5815-submodule-protos.sh
index 06f55a1..f85e71c 100755
--- a/t/t5815-submodule-protos.sh
+++ b/t/t5815-submodule-protos.sh
@@ -40,4 +40,26 @@ test_expect_success 'user can override whitelist' '
        GIT_ALLOW_PROTOCOL=ext git -C dst submodule update ext-module
 '
 
+test_expect_success 'reset dst repo for config tests' '
+       rm -rf dst &&
+       git clone . dst &&
+       git -C dst submodule init
+'
+
+test_expect_success 'update of ssh not allowed when not in config whitelist' '
+       test_must_fail git -C dst -c core.allowProtocol=none submodule update 
ssh-module
+'
+
+test_expect_success 'update of ssh allowed via config whitelist' '
+       git -C dst -c core.allowProtocol="ssh:http:https" submodule update 
ssh-module
+'
+
+test_expect_success 'update of ext not allowed' '
+       test_must_fail git -C dst -c core.allowProtocol=ssh submodule update 
ext-module
+'
+
+test_expect_success 'user can override whitelist' '
+       git -C dst -c core.allowProtocol=ext submodule update ext-module
+'
+
 test_done
diff --git a/transport.c b/transport.c
index d57e8de..e3d8e88 100644
--- a/transport.c
+++ b/transport.c
@@ -652,10 +652,16 @@ static const struct string_list *protocol_whitelist(void)
 
        if (enabled < 0) {
                const char *v = getenv("GIT_ALLOW_PROTOCOL");
+               char *w = NULL;
                if (v) {
                        string_list_split(&allowed, v, ':', -1);
                        string_list_sort(&allowed);
                        enabled = 1;
+               } else if (!git_config_get_string("core.allowProtocol", &w)) {
+                       string_list_split(&allowed, w, ':', -1);
+                       string_list_sort(&allowed);
+                       enabled = 1;
+                       free(w);
                } else {
                        enabled = 0;
                }
-- 
2.8.0.rc3.226.g39d4020

Reply via email to