CVE-2023-6395: Insufficient Information (NVD-CWE-noinfo)
value: The Mock software contains a vulnerability wherein an attacker could potentially exploit privilege escalation, enabling the execution of arbitrary code with root user privileges. This weakness stems from the absence of proper sandboxing during the expansion and execution of Jinja2 templates, which may be included in certain configuration parameters. While the Mock documentation advises treating users added to the mock group as privileged, certain build systems invoking mock on behalf of users might inadvertently permit less privileged users to define configuration tags. These tags could then be passed as parameters to mock during execution, potentially leading to the utilization of Jinja2 templates for remote privilege escalation and the execution of arbitrary code as the root user on the build server.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 9.8
Published: 2024-01-16T15:15Z
Repository: https://github.com/xsuchy/templated-dictionary
Language: Python
Files changed: templated_dictionary/__init__.py
Commit date: 2023-12-11 10:07:21 +0100
Commit message: Use a sandboxed jinja2 environment

The task of templated_dictionary object is pretty simple, it just
expands precisely defined set of templates (dictionary attributes).
Having a full power of Python interpreter in templates doesn't seem to
make any sense.  So let's make the library safer.

Diff: diff --git a/templated_dictionary/__init__.py b/templated_dictionary/__init__.py
index 994166a..ec004c0 100644
--- a/templated_dictionary/__init__.py
+++ b/templated_dictionary/__init__.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 # vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=python:textwidth=0:
 
 from collections.abc import MutableMapping
-import jinja2
+from jinja2 import sandbox
 
 
 # pylint: disable=no-member,unsupported-assignment-operation
 class TemplatedDictionary(MutableMapping):
     """ Dictionary where __getitem__() is run through Jinja2 template """
@@ -17,10 +17,12 @@ class TemplatedDictionary(MutableMapping):
         When specified, and one of the aliases is accessed - the
         'aliased_to' config option is returned.
         '''
         self.__dict__.update(*args, **kwargs)
 
+        self.sandbox = sandbox.SandboxedEnvironment(keep_trailing_newline=True)
+
         self._aliases = {}
         if alias_spec:
             for aliased_to, aliases in alias_spec.items():
                 for alias in aliases:
                     self._aliases[alias] = aliased_to
@@ -78,12 +80,11 @@ class TemplatedDictionary(MutableMapping):
 
     def __render_string(self, value):
         orig = last = value
         max_recursion = self.__dict__.get('jinja_max_recursion', 5)
         for _ in range(max_recursion):
-            template = jinja2.Template(value, keep_trailing_newline=True)
-            value = _to_native(template.render(self.__dict__))
+            value = _to_native(self.sandbox.from_string(value).render(self.__dict__, func=lambda:None))
             if value == last:
                 return value
             last = value
         raise ValueError("too deep jinja re-evaluation on '{}'".format(orig))
 

Vulnerable code: import jinja2
            template = jinja2.Template(value, keep_trailing_newline=True)
            value = _to_native(template.render(self.__dict__))
Fixed code: from jinja2 import sandbox
        self.sandbox = sandbox.SandboxedEnvironment(keep_trailing_newline=True)

            value = _to_native(self.sandbox.from_string(value).render(self.__dict__, func=lambda:None))