Skip to content

Commit d87d54b

Browse files
fix: setup security issue (#318)
* Adding tarfile member sanitization to extractall() * fix: flake8 issues after security pr Co-authored-by: TrellixVulnTeam <[email protected]>
1 parent 55f2a64 commit d87d54b

File tree

7 files changed

+83
-39
lines changed

7 files changed

+83
-39
lines changed

.flake8

Lines changed: 0 additions & 5 deletions
This file was deleted.

MANIFEST

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# file GENERATED by distutils, do NOT edit
2+
CHANGELOG.md
3+
CONTRIBUTING.md
4+
LICENSE
5+
README.md
6+
RELEASING.md
7+
requirements_dev.txt
8+
setup.cfg
9+
setup.py
10+
pact/__init__.py
11+
pact/__version__.py
12+
pact/broker.py
13+
pact/constants.py
14+
pact/consumer.py
15+
pact/http_proxy.py
16+
pact/matchers.py
17+
pact/message_consumer.py
18+
pact/message_pact.py
19+
pact/message_provider.py
20+
pact/pact.py
21+
pact/provider.py
22+
pact/verifier.py
23+
pact/verify_wrapper.py
24+
pact/bin/pact-1.88.83-linux-x86.tar.gz
25+
pact/bin/pact-1.88.83-linux-x86_64.tar.gz
26+
pact/bin/pact-1.88.83-osx.tar.gz
27+
pact/bin/pact-1.88.83-win32.zip
28+
pact/cli/__init__.py
29+
pact/cli/verify.py

pact/verify_wrapper.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from os.path import isdir, join, isfile
1010
from os import listdir
1111

12+
1213
def capture_logs(process, verbose):
1314
"""Capture logs from ruby process."""
1415
result = ''
@@ -162,14 +163,14 @@ def call_verify(
162163
command.extend(all_pact_urls)
163164
command.extend(['{}={}'.format(k, v) for k, v in options.items() if v])
164165

165-
if(provider_app_version):
166+
if (provider_app_version):
166167
command.extend(["--provider-app-version",
167168
provider_app_version])
168169

169-
if(kwargs.get('publish_verification_results', False) is True):
170+
if (kwargs.get('publish_verification_results', False) is True):
170171
command.extend(['--publish-verification-results'])
171172

172-
if(kwargs.get('verbose', False) is True):
173+
if (kwargs.get('verbose', False) is True):
173174
command.extend(['--verbose'])
174175

175176
if enable_pending:

requirements_dev.txt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
Click>=2.0.0
1+
Click>=8.1.3
22
coverage==5.4
3-
Flask==1.1.4
3+
Flask==2.2.2
44
configparser==3.5.0
5-
flake8==3.8.3
5+
flake8==5.0.4
66
mock==3.0.5
7-
psutil==5.7.0
8-
pycodestyle==2.6.0
7+
psutil==5.9.4
8+
pycodestyle==2.9.0
99
pydocstyle==4.0.1
10-
tox==3.14.0
10+
tox==3.27.1
1111
pytest==7.1.3
1212
pytest-cov==2.11.1
13-
requests>=2.26.0
14-
tox-travis==0.8
15-
urllib3>=1.26.5
13+
requests>=2.28.0
14+
urllib3>=1.26.12
15+
uvicorn>=0.19.0
1616
wheel==0.38.0
17-
markupsafe==2.0.1
17+
markupsafe==2.1.1
18+
httpx==0.23.1

setup.cfg

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ exclude_lines =
44
pragma: no cover
55

66
[flake8]
7-
max-complexity=10
8-
max-line-length=79
9-
exclude = .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.direnv
7+
ignore = E226,E302,E41,W503
8+
max-line-length = 160
9+
max-complexity = 12
10+
exclude = .git,build,dist,venv,.venv,.tox,.pytest_cache,.direnv
1011

1112
[nosetests]
1213
with-coverage=true

setup.py

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@
2828
exec(f.read(), about)
2929

3030
class sdist(sdist_orig):
31-
"""
32-
Subclass sdist so that we can download all standalone ruby applications
33-
into ./pact/bin so our users receive all the binaries on pip install.
34-
"""
31+
"""Subclass sdist to download all standalone ruby applications into ./pact/bin."""
32+
3533
def run(self):
34+
"""Installs the dist."""
3635
package_bin_path = os.path.join(os.path.dirname(__file__), 'pact', 'bin')
3736

3837
if os.path.exists(package_bin_path):
@@ -79,12 +78,12 @@ class PactPythonInstallCommand(install):
7978
user_options = install.user_options + [('bin-path=', None, None)]
8079

8180
def initialize_options(self):
82-
"""Load our preconfigured options"""
81+
"""Load our preconfigured options."""
8382
install.initialize_options(self)
8483
self.bin_path = None
8584

8685
def finalize_options(self):
87-
"""Load provided CLI arguments into our options"""
86+
"""Load provided CLI arguments into our options."""
8887
install.finalize_options(self)
8988

9089
def run(self):
@@ -124,7 +123,7 @@ def install_ruby_app(package_bin_path: str, download_bin_path=None):
124123

125124
def ruby_app_binary():
126125
"""
127-
Determines the ruby app binary required for this OS.
126+
Determine the ruby app binary required for this OS.
128127
129128
:return A dictionary of type {'filename': string, 'version': string, 'suffix': string }
130129
"""
@@ -151,7 +150,7 @@ def ruby_app_binary():
151150

152151
def download_ruby_app_binary(path_to_download_to, filename, suffix):
153152
"""
154-
Downloads `binary` into `path_to_download_to`.
153+
Download `binary` into `path_to_download_to`.
155154
156155
:param path_to_download_to: The path where binaries should be downloaded.
157156
:param filename: The filename that should be installed.
@@ -177,7 +176,7 @@ def download_ruby_app_binary(path_to_download_to, filename, suffix):
177176

178177
def extract_ruby_app_binary(source, destination, binary):
179178
"""
180-
Extracts the ruby app binary from `source` into `destination`.
179+
Extract the ruby app binary from `source` into `destination`.
181180
182181
:param source: The location of the binary to unarchive.
183182
:param destination: The location to unarchive to.
@@ -189,8 +188,25 @@ def extract_ruby_app_binary(source, destination, binary):
189188
f.extractall(destination)
190189
else:
191190
with tarfile.open(path) as f:
192-
f.extractall(destination)
191+
def is_within_directory(directory, target):
192+
193+
abs_directory = os.path.abspath(directory)
194+
abs_target = os.path.abspath(target)
195+
196+
prefix = os.path.commonprefix([abs_directory, abs_target])
197+
198+
return prefix == abs_directory
199+
200+
def safe_extract(tar, path=".", members=None, *, numeric_owner=False):
201+
202+
for member in tar.getmembers():
203+
member_path = os.path.join(path, member.name)
204+
if not is_within_directory(path, member_path):
205+
raise Exception("Attempted Path Traversal in Tar File")
206+
207+
tar.extractall(path, members, numeric_owner=numeric_owner)
193208

209+
safe_extract(f, destination)
194210

195211
def read(filename):
196212
"""Read file contents."""
@@ -200,13 +216,14 @@ def read(filename):
200216

201217

202218
dependencies = [
203-
'click>=2.0.0',
204-
'psutil>=2.0.0',
205-
'requests>=2.26.0',
206-
'six>=1.9.0',
219+
'click>=8.1.3',
220+
'psutil>=5.9.4',
221+
'requests>=2.28.0',
222+
'six>=1.16.0',
207223
'fastapi>=0.67.0',
208-
'urllib3>=1.26.5',
209-
'uvicorn>=0.14.0'
224+
'urllib3>=1.26.12',
225+
'uvicorn>=0.19.0',
226+
'httpx==0.23.1'
210227
]
211228

212229
if __name__ == '__main__':

tox.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ envlist=py{36,37,38,39,310}-{test,install}
44
deps=
55
test: -rrequirements_dev.txt
66
commands=
7-
test: pytest --cov pact tests
8-
install: python -c "import pact"
7+
test: pytest --cov pact tests
8+
install: python -c "import pact"

0 commit comments

Comments
 (0)