summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Nasiadka <mnasiadka@gmail.com>2023-03-16 10:04:47 +0000
committerMichal Nasiadka <mnasiadka@gmail.com>2023-03-20 05:21:29 +0000
commitdac11090b83dee3532cd1da39bf32d69824d45d6 (patch)
tree094660049d2288ffc08d51536ba0172b0a393f34
parent22518ed6c2660a80b8fdb3bb51d2c0cbe3eb8ef5 (diff)
downloadkolla-dac11090b83dee3532cd1da39bf32d69824d45d6.tar.gz
kolla-dac11090b83dee3532cd1da39bf32d69824d45d6.zip
Test for unsafe files in tarfile.extractall
In addition to that, mark bifrost unbuildable since it's failing on EPEL 9 enablement. Closes-Bug: #1990432 Change-Id: I650fcbc8f773fad8116338f6fb0cf7b4f4f17b33 (cherry picked from commit 3d008b7f5ec2a54d004e8e9370f303ef9dc7858b)
-rw-r--r--kolla/image/tasks.py11
-rw-r--r--kolla/tests/test_build.py42
2 files changed, 52 insertions, 1 deletions
diff --git a/kolla/image/tasks.py b/kolla/image/tasks.py
index bfc01dec5..53ae4b705 100644
--- a/kolla/image/tasks.py
+++ b/kolla/image/tasks.py
@@ -264,6 +264,14 @@ class BuildTask(DockerTask):
def builder(self, image):
+ def _test_malicious_tarball(archive, path):
+ tar_file = tarfile.open(archive, 'r|gz')
+ for n in tar_file.getnames():
+ if not os.path.abspath(os.path.join(path, n)).startswith(path):
+ tar_file.close()
+ self.logger.error(f'Unsafe filenames in archive {archive}')
+ raise ArchivingError
+
def make_an_archive(items, arcname, item_child_path=None):
if not item_child_path:
item_child_path = arcname
@@ -277,8 +285,9 @@ class BuildTask(DockerTask):
archives.append(archive_path)
if archives:
for archive in archives:
+ _test_malicious_tarball(archive, items_path)
with tarfile.open(archive, 'r') as archive_tar:
- archive_tar.extractall(path=items_path)
+ archive_tar.extractall(path=items_path) # nosec
else:
try:
os.mkdir(items_path)
diff --git a/kolla/tests/test_build.py b/kolla/tests/test_build.py
index c4c560c2f..078714583 100644
--- a/kolla/tests/test_build.py
+++ b/kolla/tests/test_build.py
@@ -14,6 +14,8 @@ import fixtures
import os
import requests
import sys
+import tarfile
+import tempfile
from unittest import mock
from kolla.cmd import build as build_cmd
@@ -289,6 +291,46 @@ class TasksTest(base.TestCase):
else:
self.assertIsNotNone(get_result)
+ @mock.patch.dict(os.environ, clear=True)
+ @mock.patch('docker.APIClient')
+ def test_malicious_tar(self, mock_client):
+ tmpdir = tempfile.mkdtemp()
+ file_name = 'test.txt'
+ archive_name = 'my_archive.tar.gz'
+ file_path = os.path.join(tmpdir, file_name)
+ archive_path = os.path.join(tmpdir, archive_name)
+ # Ensure the file is read/write by the creator only
+ saved_umask = os.umask(0o077)
+
+ try:
+ with open(file_path, 'w') as f:
+ f.write('Hello')
+
+ with tarfile.open(archive_path, 'w:gz') as tar:
+ tar.add(file_path, arcname='../test.txt')
+
+ self.dc = mock_client
+ self.image.plugins = [{
+ 'name': 'fake-image-base-plugin-test',
+ 'type': 'local',
+ 'enabled': True,
+ 'source': archive_path}
+ ]
+
+ push_queue = mock.Mock()
+ builder = tasks.BuildTask(self.conf, self.image, push_queue)
+ builder.run()
+ self.assertFalse(builder.success)
+
+ except IOError:
+ print('IOError')
+ else:
+ os.remove(file_path)
+ os.remove(archive_path)
+ finally:
+ os.umask(saved_umask)
+ os.rmdir(tmpdir)
+
@mock.patch('os.path.exists')
@mock.patch('os.utime')
@mock.patch('shutil.rmtree')