Skip to content

Commit 6cbae0e

Browse files
Merge pull request #61 from browserstack/python_binding_security_issues
Fixes for security issues
2 parents 2172ec1 + 6b59d42 commit 6cbae0e

4 files changed

Lines changed: 25 additions & 8 deletions

File tree

.github/workflows/Semgrep.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727

2828
container:
2929
# A Docker image with Semgrep installed. Do not change this.
30-
image: returntocorp/semgrep
30+
image: returntocorp/semgrep@sha256:9349edbadf90c3f3c0c3f55867625354e89680e6fa10d9034042af52fdb0e0d0
3131

3232
# Skip any PR created by dependabot to avoid permission issues:
3333
if: (github.actor != 'dependabot[bot]')

browserstack/local.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import subprocess, os, time, json,logging
1+
import subprocess, os, time, json, logging, re
22
import psutil
33

44
from browserstack.local_binary import LocalBinary
@@ -70,7 +70,16 @@ def start(self, **kwargs):
7070
del self.options['key']
7171

7272
if 'binarypath' in self.options:
73-
self.binary_path = self.options['binarypath']
73+
candidate = os.path.realpath(self.options['binarypath'])
74+
if not os.path.isfile(candidate):
75+
raise BrowserStackLocalError('binarypath does not point to a file')
76+
try:
77+
version_output = subprocess.check_output([candidate, '--version'], timeout=10).decode('utf-8')
78+
except (subprocess.SubprocessError, OSError) as e:
79+
raise BrowserStackLocalError('binarypath failed verification: {}'.format(e))
80+
if not re.match(LocalBinary.VERSION_REGEX, version_output):
81+
raise BrowserStackLocalError('binarypath failed verification')
82+
self.binary_path = candidate
7483
del self.options['binarypath']
7584
else:
7685
l = LocalBinary(self.key)
@@ -90,10 +99,18 @@ def start(self, **kwargs):
9099
if 'source' in self.options:
91100
del self.options['source']
92101

102+
logfile_dir = os.path.dirname(self.local_logfile_path)
103+
if logfile_dir:
104+
os.makedirs(logfile_dir, exist_ok=True)
105+
try:
106+
with open(self.local_logfile_path, 'w') as f:
107+
f.write('')
108+
except OSError as e:
109+
raise BrowserStackLocalError('Unable to open logfile: {}'.format(e))
110+
93111
self.proc = subprocess.Popen(self._generate_cmd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
94112
(out, err) = self.proc.communicate()
95113

96-
os.system('echo "" > "'+ self.local_logfile_path +'"')
97114
try:
98115
if out:
99116
output_string = out.decode()

browserstack/local_binary.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from urllib2 import urlopen, Request
1010

1111
class LocalBinary:
12+
VERSION_REGEX = r"BrowserStack Local version \d+\.\d+"
1213
_version = None
1314

1415
def __init__(self, key, error_object=None):
@@ -159,8 +160,7 @@ def read_chunk(chunk_size):
159160
def __verify_binary(self,path):
160161
try:
161162
binary_response = subprocess.check_output([path,"--version"]).decode("utf-8")
162-
pattern = re.compile("BrowserStack Local version \d+\.\d+")
163-
return bool(pattern.match(binary_response))
163+
return bool(re.match(LocalBinary.VERSION_REGEX, binary_response))
164164
except:
165165
return False
166166

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
setup(
66
name = 'browserstack-local',
77
packages = ['browserstack'],
8-
version = '1.2.14',
8+
version = '1.2.15',
99
description = 'Python bindings for Browserstack Local',
1010
long_description=open('README.md').read(),
1111
long_description_content_type='text/markdown',
@@ -16,7 +16,7 @@
1616
keywords = ['BrowserStack', 'Local', 'selenium', 'testing'],
1717
classifiers = [],
1818
install_requires=[
19-
'psutil',
19+
'psutil>=5.6.6,<7',
2020
],
2121
)
2222

0 commit comments

Comments
 (0)