From f95c81bf21c177f7e6a2c53ea0613034326329bd Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Tue, 1 Dec 2009 15:08:29 +0100
Subject: [PATCH] Security issue: add validation of script names

This patch unifies the search for external script to always go through
utils.FindFile and implements in that function a restriction on valid
chars in file names and (additionally) that the passed name is the
basename of the final (absolute) name.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 lib/backend.py |  7 ++++---
 lib/utils.py   | 10 +++++++++-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/lib/backend.py b/lib/backend.py
index 44e45f63a..30984b38f 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -1658,10 +1658,11 @@ def OSFromDisk(name, base_dir=None):
   """
   if base_dir is None:
     os_dir = utils.FindFile(name, constants.OS_SEARCH_PATH, os.path.isdir)
-    if os_dir is None:
-      raise errors.InvalidOS(name, None, "OS dir not found in search path")
   else:
-    os_dir = os.path.sep.join([base_dir, name])
+    os_dir = utils.FindFile(name, [base_dir], os.path.isdir)
+
+  if os_dir is None:
+    raise errors.InvalidOS(name, None, "OS dir not found in search path")
 
   api_versions = _OSOndiskVersion(name, os_dir)
 
diff --git a/lib/utils.py b/lib/utils.py
index df2d18027..bcd8e107b 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -1633,9 +1633,17 @@ def FindFile(name, search_path, test=os.path.exists):
   @return: full path to the object if found, None otherwise
 
   """
+  # validate the filename mask
+  if constants.EXT_PLUGIN_MASK.match(name) is None:
+    logging.critical("Invalid value passed for external script name: '%s'",
+                     name)
+    return None
+
   for dir_name in search_path:
     item_name = os.path.sep.join([dir_name, name])
-    if test(item_name):
+    # check the user test and that we're indeed resolving to the given
+    # basename
+    if test(item_name) and os.path.basename(item_name) == name:
       return item_name
   return None
 
-- 
GitLab