From d4aa8ee09e2d6e6676ed2dd7144d541e359fef7e Mon Sep 17 00:00:00 2001 From: Michal Nasiadka Date: Wed, 10 Jun 2026 17:27:50 +0100 Subject: kolla-build: Use SandboxedEnvironment to prevent SSTI Switch from jinja2.Environment to jinja2.sandbox.SandboxedEnvironment to block Server-Side Template Injection attacks. Closes-Bug: #2146056 Change-Id: Iecd1d8dcf99007e3339120961c7c1d0ca12f83d8 Signed-off-by: Michal Nasiadka (cherry picked from commit 0b20ffce09552014fa52c45de574511dc2200ac5) --- kolla/tests/test_build.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'kolla/tests/test_build.py') diff --git a/kolla/tests/test_build.py b/kolla/tests/test_build.py index deb2dfa10..82bcb7d6d 100644 --- a/kolla/tests/test_build.py +++ b/kolla/tests/test_build.py @@ -11,6 +11,7 @@ # limitations under the License. import fixtures +import jinja2 import os import requests import sys @@ -579,6 +580,72 @@ class KollaWorkerTest(base.TestCase): kolla.setup_working_dir() kolla.set_time() + @mock.patch.dict(os.environ, {'http_proxy': 'http://test-proxy:8080'}, + clear=False) + @mock.patch(engine_client) + def test_create_dockerfiles_env_http_proxy(self, mock_client): + tmpdir = self.useFixture(fixtures.TempDir()).path + base_dir = os.path.join(tmpdir, 'base') + os.makedirs(base_dir) + with open(os.path.join(base_dir, 'Dockerfile.j2'), 'w') as f: + f.write( + '{% if env.http_proxy %}' + 'ARG http_proxy={{ env.http_proxy }}' + '{% endif %}\n' + ) + with mock.patch.object(build.KollaWorker, '_get_images_dir', + return_value=tmpdir): + kolla = build.KollaWorker(self.conf) + kolla.setup_working_dir() + kolla.find_dockerfiles() + kolla.create_dockerfiles() + dockerfile = os.path.join(kolla.working_dir, 'base', 'Dockerfile') + with open(dockerfile) as f: + content = f.read() + self.assertIn('http://test-proxy:8080', content) + + @mock.patch(engine_client) + def test_create_dockerfiles_ssti_blocked(self, mock_client): + tmpdir = self.useFixture(fixtures.TempDir()).path + base_dir = os.path.join(tmpdir, 'base') + os.makedirs(base_dir) + with open(os.path.join(base_dir, 'Dockerfile.j2'), 'w') as f: + f.write( + "{{ self.__init__.__globals__['__builtins__']" + "['__import__']('os').popen('id').read() }}\n" + ) + with mock.patch.object(build.KollaWorker, '_get_images_dir', + return_value=tmpdir): + kolla = build.KollaWorker(self.conf) + kolla.setup_working_dir() + kolla.find_dockerfiles() + self.assertRaises(jinja2.exceptions.SecurityError, + kolla.create_dockerfiles) + + @mock.patch(engine_client) + def test_create_dockerfiles_template_override_ssti_blocked( + self, mock_client): + tmpdir = self.useFixture(fixtures.TempDir()).path + base_dir = os.path.join(tmpdir, 'base') + os.makedirs(base_dir) + with open(os.path.join(base_dir, 'Dockerfile.j2'), 'w') as f: + f.write('FROM {{ base_distro }}:{{ base_distro_tag }}\n') + override_file = os.path.join( + self.useFixture(fixtures.TempDir()).path, 'template_override.j2') + with open(override_file, 'w') as f: + f.write( + "{{ self.__init__.__globals__['__builtins__']" + "['__import__']('os').popen('id').read() }}\n" + ) + self.conf.set_override('template_override', [override_file]) + with mock.patch.object(build.KollaWorker, '_get_images_dir', + return_value=tmpdir): + kolla = build.KollaWorker(self.conf) + kolla.setup_working_dir() + kolla.find_dockerfiles() + self.assertRaises(jinja2.exceptions.SecurityError, + kolla.create_dockerfiles) + def _get_matched_images(self, images): return [image for image in images if image.status == utils.Status.MATCHED] -- cgit v1.2.3