Skip to content

Commit b4feb03

Browse files
authored
fix: use tarfile extract filters to open tarfiles more safely (#3769)
Also changed pre-commit config so interrogate is at the top and its output doesn't obscure more urgent error messages. Note that this is still missing a test and appropriate windows behaviour; those will be coming in future PRs. Signed-off-by: Terri Oda <[email protected]>
1 parent eabf69d commit b4feb03

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

.github/workflows/testing.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ jobs:
210210
- uses: technote-space/get-diff-action@f27caffdd0fb9b13f4fc191c016bb4e0632844af # v6.1.2
211211
with:
212212
PATTERNS: |
213+
cve_bin_tool/*.py
214+
cve_bin_tool/data_sources/*.py
213215
cve_bin_tool/checkers/*.py
214216
test/condensed-downloads/*
215217
FILES: |

.pre-commit-config.yaml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
repos:
2+
- repo: https://github.com/econchick/interrogate
3+
rev: 1.5.0
4+
hooks:
5+
- id: interrogate
6+
verbose: True
7+
exclude: ^(locales|presentation|fuzz|test|cve_bin_tool/checkers|build)
8+
args: ["-vv", "-i", "-I", "-M", "-C", "-n", "-p", "-f", "60.0"]
9+
210
- repo: https://github.com/pycqa/isort
311
rev: 5.13.2
412
hooks:
@@ -71,11 +79,4 @@ repos:
7179
test/utils.py|
7280
)$
7381
74-
- repo: https://github.com/econchick/interrogate
75-
rev: 1.5.0
76-
hooks:
77-
- id: interrogate
78-
verbose: True
79-
exclude: ^(locales|presentation|fuzz|test|cve_bin_tool/checkers|build)
80-
args: ["-vv", "-i", "-I", "-M", "-C", "-n", "-p", "-f", "60.0"]
8182

cve_bin_tool/extractor.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import re
99
import shutil
1010
import sys
11+
import tarfile
1112
import tempfile
1213
from pathlib import Path
1314

@@ -73,11 +74,42 @@ def can_extract(self, filename):
7374
return True
7475
return False
7576

76-
@staticmethod
77-
async def extract_file_tar(filename, extraction_path):
77+
def tar_member_filter(self, members, extraction_path):
78+
"""Generator function to serve as a backported filter for tarfile extraction
79+
based on https://docs.python.org/3/library/tarfile.html#examples
80+
"""
81+
for tarmember in members:
82+
if tarmember.isfile() and str(
83+
Path(extraction_path, tarmember.name).resolve()
84+
).startsWith(extraction_path):
85+
yield tarmember
86+
87+
async def extract_file_tar(self, filename, extraction_path):
7888
"""Extract tar files"""
89+
90+
# make sure we have full path for later checks
91+
extraction_path = str(Path(extraction_path).resolve())
7992
with ErrorHandler(mode=ErrorMode.Ignore) as e:
80-
await aio_unpack_archive(filename, extraction_path)
93+
tar = tarfile.open(filename)
94+
# Python 3.12 has a data filter we can use in extract
95+
# tarfile has this available in older versions as well
96+
if hasattr(tarfile, "data_filter"):
97+
tar.extractall(path=extraction_path, filter="data") # nosec
98+
# nosec line because bandit doesn't understand filters yet
99+
100+
# FIXME: the backported fix is not working on windows.
101+
# this leaves the current (unsafe) behaviour so we can fix at least one OS for now
102+
elif sys.platform == "win32":
103+
tar.extractall(path=extraction_path) # nosec
104+
105+
# Some versions may need us to implement a filter to avoid unsafe behaviour
106+
# we could consider logging a warning here
107+
else:
108+
tar.extractall(
109+
path=extraction_path,
110+
members=self.tar_member_filter(tar, extraction_path),
111+
) # nosec
112+
tar.close()
81113
return e.exit_code
82114

83115
async def extract_file_rpm(self, filename, extraction_path):

0 commit comments

Comments
 (0)