chiark / gitweb /
shell=True is too dangerous to allow; there are unfiltered user inputs
authorHans-Christoph Steiner <hans@eds.org>
Tue, 23 Jan 2018 22:56:15 +0000 (23:56 +0100)
committerHans-Christoph Steiner <hans@eds.org>
Fri, 26 Jan 2018 09:18:41 +0000 (10:18 +0100)
There are all sorts of unfiltered user inputs like tag and branch names in
source repos.  If those names are fed into popen calls that use shell=True,
that opens up a wide range of exploits.  All core operations should never
use shell=True.

fdroidserver/build.py
fdroidserver/vmtools.py
hooks/pre-commit

index b8229f164babe6b557f22f6b7f8446e7517799b6..ba0b0733fa605e0522445003c5afd2d357703b4d 100644 (file)
@@ -133,9 +133,9 @@ def build_server(app, build, vcs, build_dir, output_dir, log_dir, force):
         ftp.chmod('config.py', 0o600)
 
         # Copy over the ID (head commit hash) of the fdroidserver in use...
-        subprocess.call('git rev-parse HEAD >' +
-                        os.path.join(os.getcwd(), 'tmp', 'fdroidserverid'),
-                        shell=True, cwd=serverpath)
+        with open(os.path.join(os.getcwd(), 'tmp', 'fdroidserverid'), 'wb') as fp:
+            fp.write(subprocess.check_output(['git', 'rev-parse', 'HEAD'],
+                                             cwd=serverpath))
         ftp.put('tmp/fdroidserverid', 'fdroidserverid')
 
         # Copy the metadata - just the file for this app...
@@ -1263,7 +1263,7 @@ def main():
             for app in build_succeeded:
 
                 logging.info("Need to sign the app before we can install it.")
-                subprocess.call("fdroid publish {0}".format(app.id), shell=True)
+                subprocess.call("fdroid publish {0}".format(app.id))
 
                 apk_path = None
 
index 33544ac53798f192b578eb216a26cc28a3e061f3..e8281192a76bb7cbd84f8ba9c452b2865ed158bd 100644 (file)
@@ -88,14 +88,14 @@ def get_clean_builder(serverdir, reset=False):
     return sshinfo
 
 
-def _check_call(cmd, shell=False, cwd=None):
+def _check_call(cmd, cwd=None):
     logger.debug(' '.join(cmd))
-    return subprocess.check_call(cmd, shell=shell, cwd=cwd)
+    return subprocess.check_call(cmd, shell=False, cwd=cwd)
 
 
-def _check_output(cmd, shell=False, cwd=None):
+def _check_output(cmd, cwd=None):
     logger.debug(' '.join(cmd))
-    return subprocess.check_output(cmd, shell=shell, cwd=cwd)
+    return subprocess.check_output(cmd, shell=False, cwd=cwd)
 
 
 def get_build_vm(srvdir, provider=None):
@@ -303,11 +303,13 @@ class FDroidBuildVm():
         """
         import paramiko
         try:
-            _check_call(['vagrant ssh-config > sshconfig'],
-                        cwd=self.srvdir, shell=True)
+            sshconfig_path = os.path.join(self.srvdir, 'sshconfig')
+            with open(sshconfig_path, 'wb') as fp:
+                fp.write(_check_output(['vagrant', 'ssh-config'],
+                                       cwd=self.srvdir))
             vagranthost = 'default'  # Host in ssh config file
             sshconfig = paramiko.SSHConfig()
-            with open(joinpath(self.srvdir, 'sshconfig'), 'r') as f:
+            with open(sshconfig_path, 'r') as f:
                 sshconfig.parse(f)
             sshconfig = sshconfig.lookup(vagranthost)
             idfile = sshconfig['identityfile']
index 1dcc1d5aeee269568467658c3234a32b876e3e2f..5969f196b12ffede38e17700cde0e1299d6c44b7 100755 (executable)
@@ -129,4 +129,8 @@ for f in $RB_FILES; do
        fi
 done
 
+if grep --line-number 'shell=True' fdroidserver/[a-ce-z]*.py; then
+    err "shell=True is too dangerous, there are unfiltered user inputs!"
+fi
+
 exit 0