diff --git a/SOURCES/0001-submodule-allow-only-certain-protocols-for-submodule.patch b/SOURCES/0001-submodule-allow-only-certain-protocols-for-submodule.patch
new file mode 100644
index 0000000..e2067b1
--- /dev/null
+++ b/SOURCES/0001-submodule-allow-only-certain-protocols-for-submodule.patch
@@ -0,0 +1,104 @@
+From 6d69680505dbbc484178105815ed624fab40b2de Mon Sep 17 00:00:00 2001
+From: Petr Stodulka <pstodulk@redhat.com>
+Date: Wed, 28 Oct 2015 15:03:01 +0100
+Subject: [PATCH 1/5] submodule: allow only certain protocols for submodule
+ fetches
+
+Some protocols (like git-remote-ext) can execute arbitrary
+code found in the URL. The URLs that submodules use may come
+from arbitrary sources (e.g., .gitmodules files in a remote
+repository). Let's restrict submodules to fetching from a
+known-good subset of protocols.
+
+Note that we apply this restriction to all submodule
+commands, whether the URL comes from .gitmodules or not.
+This is more restrictive than we need to be; for example, in
+the tests we run:
+
+  git submodule add ext::...
+
+which should be trusted, as the URL comes directly from the
+command line provided by the user. But doing it this way is
+simpler, and makes it much less likely that we would miss a
+case. And since such protocols should be an exception
+(especially because nobody who clones from them will be able
+to update the submodules!), it's not likely to inconvenience
+anyone in practice.
+---
+ git-submodule.sh            |  9 +++++++++
+ t/t5815-submodule-protos-sh | 43 +++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 52 insertions(+)
+ create mode 100644 t/t5815-submodule-protos-sh
+
+diff --git a/git-submodule.sh b/git-submodule.sh
+index 79bfaac..bec3362 100755
+--- a/git-submodule.sh
++++ b/git-submodule.sh
+@@ -19,6 +19,15 @@ OPTIONS_SPEC=
+ . git-parse-remote
+ require_work_tree
+ 
++# Restrict ourselves to a vanilla subset of protocols; the URLs
++# we get are under control of a remote repository, and we do not
++# want them kicking off arbitrary git-remote-* programs.
++#
++# 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}
++export GIT_ALLOW_PROTOCOL
++
+ command=
+ branch=
+ force=
+diff --git a/t/t5815-submodule-protos-sh b/t/t5815-submodule-protos-sh
+new file mode 100644
+index 0000000..06f55a1
+--- /dev/null
++++ b/t/t5815-submodule-protos-sh
+@@ -0,0 +1,43 @@
++#!/bin/sh
++
++test_description='test protocol whitelisting with submodules'
++. ./test-lib.sh
++. "$TEST_DIRECTORY"/lib-proto-disable.sh
++
++setup_ext_wrapper
++setup_ssh_wrapper
++
++test_expect_success 'setup repository with submodules' '
++	mkdir remote &&
++	git init remote/repo.git &&
++	(cd remote/repo.git && test_commit one) &&
++	# submodule-add should probably trust what we feed it on the cmdline,
++	# but its implementation is overly conservative.
++	GIT_ALLOW_PROTOCOL=ssh git submodule add remote:repo.git ssh-module &&
++	GIT_ALLOW_PROTOCOL=ext git submodule add "ext::fake-remote %S repo.git" ext-module &&
++	git commit -m "add submodules"
++'
++
++test_expect_success 'clone with recurse-submodules fails' '
++	test_must_fail git clone --recurse-submodules . dst
++'
++
++test_expect_success 'setup individual updates' '
++	rm -rf dst &&
++	git clone . dst &&
++	git -C dst submodule init
++'
++
++test_expect_success 'update of ssh allowed' '
++	git -C dst submodule update ssh-module
++'
++
++test_expect_success 'update of ext not allowed' '
++	test_must_fail git -C dst submodule update ext-module
++'
++
++test_expect_success 'user can override whitelist' '
++	GIT_ALLOW_PROTOCOL=ext git -C dst submodule update ext-module
++'
++
++test_done
+-- 
+2.1.0
+
diff --git a/SOURCES/0002-transport-add-a-protocol-whitelist-environment-varia.patch b/SOURCES/0002-transport-add-a-protocol-whitelist-environment-varia.patch
new file mode 100644
index 0000000..d908739
--- /dev/null
+++ b/SOURCES/0002-transport-add-a-protocol-whitelist-environment-varia.patch
@@ -0,0 +1,207 @@
+From cfa4e13f09d07f679ffacdddfbe0ef44d1de32d9 Mon Sep 17 00:00:00 2001
+From: Petr Stodulka <pstodulk@redhat.com>
+Date: Wed, 28 Oct 2015 15:21:08 +0100
+Subject: [PATCH 2/5] transport: add a protocol-whitelist environment variable
+
+If we are cloning an untrusted remote repository into a
+sandbox, we may also want to fetch remote submodules in
+order to get the complete view as intended by the other
+side. However, that opens us up to attacks where a malicious
+user gets us to clone something they would not otherwise
+have access to (this is not necessarily a problem by itself,
+but we may then act on the cloned contents in a way that
+exposes them to the attacker).
+
+Ideally such a setup would sandbox git entirely away from
+high-value items, but this is not always practical or easy
+to set up (e.g., OS network controls may block multiple
+protocols, and we would want to enable some but not others).
+
+We can help this case by providing a way to restrict
+particular protocols. We use a whitelist in the environment.
+This is more annoying to set up than a blacklist, but
+defaults to safety if the set of protocols git supports
+grows). If no whitelist is specified, we continue to default
+to allowing all protocols (this is an "unsafe" default, but
+since the minority of users will want this sandboxing
+effect, it is the only sensible one).
+
+A note on the tests: ideally these would all be in a single
+test file, but the git-daemon and httpd test infrastructure
+is an all-or-nothing proposition rather than a test-by-test
+prerequisite. By putting them all together, we would be
+unable to test the file-local code on machines without
+apache.
+---
+ Documentation/git.txt | 32 ++++++++++++++++++++++++++++++++
+ connect.c             |  4 ++++
+ transport-helper.c    |  2 ++
+ transport.c           | 21 ++++++++++++++++++++-
+ transport.h           |  7 +++++++
+ 5 files changed, 65 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/git.txt b/Documentation/git.txt
+index 443d88f..179a0e8 100644
+--- a/Documentation/git.txt
++++ b/Documentation/git.txt
+@@ -847,6 +847,38 @@ GIT_LITERAL_PATHSPECS::
+ 	literal paths to Git (e.g., paths previously given to you by
+ 	`git ls-tree`, `--raw` diff output, etc).
+ 
++`GIT_ALLOW_PROTOCOL`::
++   If set, provide a colon-separated list of protocols which are
++   allowed to be used with fetch/push/clone. This is useful to
++   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:
++
++     - `file`: any local file-based path (including `file://` URLs,
++       or local paths)
++
++     - `git`: the anonymous git protocol over a direct TCP
++       connection (or proxy, if configured)
++
++     - `ssh`: git over ssh (including `host:path` syntax,
++       `git+ssh://`, etc).
++
++     - `rsync`: git over rsync
++
++     - `http`: git over http, both "smart http" and "dumb http".
++       Note that this does _not_ include `https`; if you want both,
++       you should specify both as `http:https`.
++
++     - any external helpers are named by their protocol (e.g., use
++       `hg` to allow the `git-remote-hg` helper)
+++
++Note that this controls only git's internal protocol selection.
++If libcurl is used (e.g., by the `http` transport), it may
++redirect to other protocols. There is not currently any way to
++restrict this.
++
+ 
+ Discussion[[Discussion]]
+ ------------------------
+diff --git a/connect.c b/connect.c
+index f57efd0..6d4ea13 100644
+--- a/connect.c
++++ b/connect.c
+@@ -6,6 +6,7 @@
+ #include "run-command.h"
+ #include "remote.h"
+ #include "url.h"
++#include "transport.h"
+ 
+ static char *server_capabilities;
+ 
+@@ -587,6 +588,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
+ 		 * cannot connect.
+ 		 */
+ 		char *target_host = xstrdup(host);
++		transport_check_allowed("git");
+ 		if (git_use_proxy(host))
+ 			conn = git_proxy_connect(fd, host);
+ 		else
+@@ -623,6 +625,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
+ 	if (protocol == PROTO_SSH) {
+ 		const char *ssh = getenv("GIT_SSH");
+ 		int putty = ssh && strcasestr(ssh, "plink");
++		transport_check_allowed("ssh");
+ 		if (!ssh) ssh = "ssh";
+ 
+ 		*arg++ = ssh;
+@@ -639,6 +642,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
+ 		/* remove repo-local variables from the environment */
+ 		conn->env = local_repo_env;
+ 		conn->use_shell = 1;
++		transport_check_allowed("file");
+ 	}
+ 	*arg++ = cmd.buf;
+ 	*arg = NULL;
+diff --git a/transport-helper.c b/transport-helper.c
+index 522d791..be8402a 100644
+--- a/transport-helper.c
++++ b/transport-helper.c
+@@ -932,6 +932,8 @@ int transport_helper_init(struct transport *transport, const char *name)
+ 	struct helper_data *data = xcalloc(sizeof(*data), 1);
+ 	data->name = name;
+ 
++	transport_check_allowed(name);
++
+ 	if (getenv("GIT_TRANSPORT_HELPER_DEBUG"))
+ 		debug = 1;
+ 
+diff --git a/transport.c b/transport.c
+index ba5d8af..733717d 100644
+--- a/transport.c
++++ b/transport.c
+@@ -894,6 +894,20 @@ static int external_specification_len(const char *url)
+ 	return strchr(url, ':') - url;
+ }
+ 
++void transport_check_allowed(const char *type)
++{
++	struct string_list allowed = STRING_LIST_INIT_DUP;
++	const char *v = getenv("GIT_ALLOW_PROTOCOL");
++
++	if (!v)
++		return;
++
++	string_list_split(&allowed, v, ':', -1);
++	if (!unsorted_string_list_has_string(&allowed, type))
++		die("transport '%s' not allowed", type);
++	string_list_clear(&allowed, 0);
++}
++
+ struct transport *transport_get(struct remote *remote, const char *url)
+ {
+ 	const char *helper;
+@@ -925,12 +939,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
+ 	if (helper) {
+ 		transport_helper_init(ret, helper);
+ 	} else if (!prefixcmp(url, "rsync:")) {
++		transport_check_allowed("rsync");
+ 		ret->get_refs_list = get_refs_via_rsync;
+ 		ret->fetch = fetch_objs_via_rsync;
+ 		ret->push = rsync_transport_push;
+ 		ret->smart_options = NULL;
+ 	} else if (is_local(url) && is_file(url) && is_bundle(url, 1)) {
+ 		struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
++		transport_check_allowed("file");
+ 		ret->data = data;
+ 		ret->get_refs_list = get_refs_from_bundle;
+ 		ret->fetch = fetch_refs_from_bundle;
+@@ -942,7 +958,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
+ 		|| !prefixcmp(url, "ssh://")
+ 		|| !prefixcmp(url, "git+ssh://")
+ 		|| !prefixcmp(url, "ssh+git://")) {
+-		/* These are builtin smart transports. */
++		/*
++		 * These are builtin smart transports; "allowed" transports
++		 * will be checked individually in git_connect.
++		 */
+ 		struct git_transport_data *data = xcalloc(1, sizeof(*data));
+ 		ret->data = data;
+ 		ret->set_option = NULL;
+diff --git a/transport.h b/transport.h
+index fcb1d25..2beda7d 100644
+--- a/transport.h
++++ b/transport.h
+@@ -113,6 +113,13 @@ struct transport {
+ /* Returns a transport suitable for the url */
+ struct transport *transport_get(struct remote *, const char *);
+ 
++/*
++ * Check whether a transport is allowed by the environment,
++ * and die otherwise. type should generally be the URL scheme,
++ * as described in Documentation/git.txt
++ */
++void transport_check_allowed(const char *type);
++
+ /* Transport options which apply to git:// and scp-style URLs */
+ 
+ /* The program to use on the remote side to send a pack */
+-- 
+2.1.0
+
diff --git a/SOURCES/0003-transport-refactor-protocol-whitelist-code.patch b/SOURCES/0003-transport-refactor-protocol-whitelist-code.patch
new file mode 100644
index 0000000..ff5416d
--- /dev/null
+++ b/SOURCES/0003-transport-refactor-protocol-whitelist-code.patch
@@ -0,0 +1,107 @@
+From 9b9aabe6ab5d07227c1c02781f03a3c38fbc27b0 Mon Sep 17 00:00:00 2001
+From: Jeff King <peff@peff.net>
+Date: Tue, 22 Sep 2015 18:03:49 -0400
+Subject: [PATCH 3/5] transport: refactor protocol whitelist code
+
+The current callers only want to die when their transport is
+prohibited. But future callers want to query the mechanism
+without dying.
+
+Let's break out a few query functions, and also save the
+results in a static list so we don't have to re-parse for
+each query.
+
+Based-on-a-patch-by: Blake Burkhart <bburky@bburky.com>
+Signed-off-by: Jeff King <peff@peff.net>
+Signed-off-by: Junio C Hamano <gitster@pobox.com>
+---
+ transport.c | 38 ++++++++++++++++++++++++++++++--------
+ transport.h | 15 +++++++++++++--
+ 2 files changed, 43 insertions(+), 10 deletions(-)
+
+diff --git a/transport.c b/transport.c
+index 733717d..2dbdca0 100644
+--- a/transport.c
++++ b/transport.c
+@@ -894,18 +894,40 @@ static int external_specification_len(const char *url)
+ 	return strchr(url, ':') - url;
+ }
+ 
+-void transport_check_allowed(const char *type)
++static const struct string_list *protocol_whitelist(void)
+ {
+-	struct string_list allowed = STRING_LIST_INIT_DUP;
+-	const char *v = getenv("GIT_ALLOW_PROTOCOL");
++	static int enabled = -1;
++	static struct string_list allowed = STRING_LIST_INIT_DUP;
++
++	if (enabled < 0) {
++		const char *v = getenv("GIT_ALLOW_PROTOCOL");
++		if (v) {
++			string_list_split(&allowed, v, ':', -1);
++			sort_string_list(&allowed);
++			enabled = 1;
++		} else {
++			enabled = 0;
++		}
++	}
+ 
+-	if (!v)
+-		return;
++	return enabled ? &allowed : NULL;
++}
++
++int is_transport_allowed(const char *type)
++{
++	const struct string_list *allowed = protocol_whitelist();
++	return !allowed || string_list_has_string(allowed, type);
++}
+ 
+-	string_list_split(&allowed, v, ':', -1);
+-	if (!unsorted_string_list_has_string(&allowed, type))
++void transport_check_allowed(const char *type)
++{
++	if (!is_transport_allowed(type))
+ 		die("transport '%s' not allowed", type);
+-	string_list_clear(&allowed, 0);
++}
++
++int transport_restrict_protocols(void)
++{
++	return !!protocol_whitelist();
+ }
+ 
+ struct transport *transport_get(struct remote *remote, const char *url)
+diff --git a/transport.h b/transport.h
+index 2beda7d..7707c27 100644
+--- a/transport.h
++++ b/transport.h
+@@ -114,12 +114,23 @@ struct transport {
+ struct transport *transport_get(struct remote *, const char *);
+ 
+ /*
++ * Check whether a transport is allowed by the environment. Type should
++ * generally be the URL scheme, as described in Documentation/git.txt
++ */
++int is_transport_allowed(const char *type);
++
++/*
+  * Check whether a transport is allowed by the environment,
+- * and die otherwise. type should generally be the URL scheme,
+- * as described in Documentation/git.txt
++ * and die otherwise.
+  */
+ void transport_check_allowed(const char *type);
+ 
++/*
++ * Returns true if the user has attempted to turn on protocol
++ * restrictions at all.
++ */
++int transport_restrict_protocols(void);
++
+ /* Transport options which apply to git:// and scp-style URLs */
+ 
+ /* The program to use on the remote side to send a pack */
+-- 
+2.1.0
+
diff --git a/SOURCES/0004-http-limit-redirection-to-protocol-whitelist.patch b/SOURCES/0004-http-limit-redirection-to-protocol-whitelist.patch
new file mode 100644
index 0000000..293f16c
--- /dev/null
+++ b/SOURCES/0004-http-limit-redirection-to-protocol-whitelist.patch
@@ -0,0 +1,77 @@
+From 2d22150270739cd29d0ac6bc329e0a2e2910d7d9 Mon Sep 17 00:00:00 2001
+From: Petr Stodulka <pstodulk@redhat.com>
+Date: Fri, 23 Oct 2015 17:36:57 +0200
+Subject: [PATCH 4/5] http-limit-redirection-to-protocol-whitelist
+
+Previously, libcurl would follow redirection to any protocol
+it was compiled for support with. This is desirable to allow
+redirection from HTTP to HTTPS. However, it would even
+successfully allow redirection from HTTP to SFTP, a protocol
+that git does not otherwise support at all. Furthermore
+git's new protocol-whitelisting could be bypassed by
+following a redirect within the remote helper, as it was
+only enforced at transport selection time.
+
+This patch limits redirects within libcurl to HTTP, HTTPS,
+FTP and FTPS. If there is a protocol-whitelist present, this
+list is limited to those also allowed by the whitelist. As
+redirection happens from within libcurl, it is impossible
+for an HTTP redirect to a protocol implemented within
+another remote helper.
+
+When the curl version git was compiled with is too old to
+support restrictions on protocol redirection, we warn the
+user if GIT_ALLOW_PROTOCOL restrictions were requested. This
+is a little inaccurate, as even without that variable in the
+environment, we would still restrict SFTP, etc, and we do
+not warn in that case. But anything else means we would
+literally warn every time git accesses an http remote.
+---
+ http.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/http.c b/http.c
+index 92aba59..235c2d5 100644
+--- a/http.c
++++ b/http.c
+@@ -6,6 +6,7 @@
+ #include "credential.h"
+ #include "version.h"
+ #include "pkt-line.h"
++#include "transport.h"
+ 
+ int active_requests;
+ int http_is_verbose;
+@@ -252,6 +253,7 @@ static int has_cert_password(void)
+ static CURL *get_curl_handle(void)
+ {
+ 	CURL *result = curl_easy_init();
++	long allowed_protocols = 0;
+ 
+ 	if (!curl_ssl_verify) {
+ 		curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
+@@ -301,6 +303,21 @@ static CURL *get_curl_handle(void)
+ #elif LIBCURL_VERSION_NUM >= 0x071101
+ 	curl_easy_setopt(result, CURLOPT_POST301, 1);
+ #endif
++#if LIBCURL_VERSION_NUM >= 0x071304
++	if (is_transport_allowed("http"))
++		allowed_protocols |= CURLPROTO_HTTP;
++	if (is_transport_allowed("https"))
++		allowed_protocols |= CURLPROTO_HTTPS;
++	if (is_transport_allowed("ftp"))
++		allowed_protocols |= CURLPROTO_FTP;
++	if (is_transport_allowed("ftps"))
++		allowed_protocols |= CURLPROTO_FTPS;
++	curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols);
++#else
++	if (transport_restrict_protocols())
++		warning("protocol restrictions not applied to curl redirects because\n"
++			"your curl version is too old (>= 7.19.4)");
++#endif
+ 
+ 	if (getenv("GIT_CURL_VERBOSE"))
+ 		curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
+-- 
+2.1.0
+
diff --git a/SOURCES/0005-http-limit-redirection-depth.patch b/SOURCES/0005-http-limit-redirection-depth.patch
new file mode 100644
index 0000000..471f4eb
--- /dev/null
+++ b/SOURCES/0005-http-limit-redirection-depth.patch
@@ -0,0 +1,31 @@
+From 7f3bfdbc2670b4960242fa1b229dde6bcb2b463b Mon Sep 17 00:00:00 2001
+From: Petr Stodulka <pstodulk@redhat.com>
+Date: Fri, 23 Oct 2015 17:39:59 +0200
+Subject: [PATCH 5/5] http: limit redirection depth
+
+By default, libcurl will follow circular http redirects
+forever. Let's put a cap on this so that somebody who can
+trigger an automated fetch of an arbitrary repository (e.g.,
+for CI) cannot convince git to loop infinitely.
+
+The value chosen is 20, which is the same default that
+Firefox uses.
+---
+ http.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/http.c b/http.c
+index 235c2d5..a1c7dcb 100644
+--- a/http.c
++++ b/http.c
+@@ -298,6 +298,7 @@ static CURL *get_curl_handle(void)
+ 	}
+ 
+ 	curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
++	curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20);
+ #if LIBCURL_VERSION_NUM >= 0x071301
+ 	curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
+ #elif LIBCURL_VERSION_NUM >= 0x071101
+-- 
+2.1.0
+
diff --git a/SPECS/git.spec b/SPECS/git.spec
index 2300f11..6a9d241 100644
--- a/SPECS/git.spec
+++ b/SPECS/git.spec
@@ -51,7 +51,7 @@
 
 Name:           git
 Version:        1.8.3.1
-Release:        5%{?dist}
+Release:        6%{?dist}
 Summary:        Fast Version Control System
 License:        GPLv2
 Group:          Development/Tools
@@ -76,6 +76,13 @@ Patch5:         0001-git-subtree-Use-gitexecdir-instead-of-libexecdir.patch
 # find a proper solution.
 Patch6:         0001-Drop-DESTDIR-from-python-instlibdir.patch
 
+# whole set is for https://bugzilla.redhat.com/show_bug.cgi?id=1273889
+Patch7:         0001-submodule-allow-only-certain-protocols-for-submodule.patch
+Patch8:         0002-transport-add-a-protocol-whitelist-environment-varia.patch
+Patch9:         0003-transport-refactor-protocol-whitelist-code.patch
+Patch10:        0004-http-limit-redirection-to-protocol-whitelist.patch
+Patch11:        0005-http-limit-redirection-depth.patch
+
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 %if ! %{use_prebuilt_docs} && ! 0%{?_without_docs}
@@ -318,6 +325,11 @@ Requires:       emacs-git = %{version}-%{release}
 %endif
 %patch5 -p1
 %patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
 
 %if %{use_prebuilt_docs}
 mkdir -p prebuilt_docs/{html,man}
@@ -643,6 +655,10 @@ rm -rf %{buildroot}
 # No files for you!
 
 %changelog
+* Wed Oct 28 2015 Petr Stodulka <pstodulk@redhat.com> - 1.8.3.1-6
+- fix arbitrary code execution via crafted URLs
+  Resolves: #1274737
+
 * Fri Jun 19 2015 Petr Stodulka <pstodulk@redhat.com> - 1.8.3.1-5
 - Rename the git.service into git@.service
   Resolves #1135071