diff --git a/lti_auth/auth.py b/lti_auth/auth.py index e4d4b4f55..7deb2a5e6 100644 --- a/lti_auth/auth.py +++ b/lti_auth/auth.py @@ -27,7 +27,7 @@ def get_hashed_username(self, lti): # sha1 hash result + trunc to 30 chars should result in a valid # username with low-ish-chance of collisions uid = lti.consumer_user_id() - return sha1(smart_bytes(uid)).hexdigest()[:30] + return sha1(smart_bytes(uid), usedforsecurity=False).hexdigest()[:30] def get_username(self, lti): username = lti.user_identifier() diff --git a/mediathread/assetmgr/sligen.py b/mediathread/assetmgr/sligen.py index 471253ff2..a1864458c 100644 --- a/mediathread/assetmgr/sligen.py +++ b/mediathread/assetmgr/sligen.py @@ -65,10 +65,10 @@ def sligen_streaming_processor(url, label=None, request=None): # noqa: C901 if jw_url is not None: return jw_url - response = requests.get(url) + response = requests.get(url, timeout=60) data = response.json() manifest_url = data['playlist'][0]['sources'][0]['file'] - response = requests.get(manifest_url) + response = requests.get(manifest_url, timeout=60) lines = response.content.decode('utf-8').split('\n') jw_url = lines[2] cache.set(url, jw_url, 10800) @@ -83,7 +83,9 @@ def sligen_streaming_processor(url, label=None, request=None): # noqa: C901 prefix = getattr(settings, 'CCNMTLSTREAM_PREFIX', None) t_hex = '%08x' % round(time.time()) m = hashlib.md5( - (secret + filename + t_hex).encode('utf-8')).hexdigest() + (secret + filename + t_hex).encode('utf-8'), + usedforsecurity=False + ).hexdigest() return '%s/%s/%s/%s' % (prefix, m, t_hex, filename) flvstream_prefix = getattr(settings, 'FLVSTREAM_PREFIX', None) @@ -102,7 +104,8 @@ def sligen_streaming_processor(url, label=None, request=None): # noqa: C901 url_slashed[5] = hashlib.sha1( '{}{}{}{}'.format( - filename, dechex, address, SECRET).encode('utf-8') + filename, dechex, address, SECRET).encode('utf-8'), + usedforsecurity=False ).hexdigest() return '%s?pos=${start}' % '/'.join(url_slashed) diff --git a/mediathread/assetmgr/utils.py b/mediathread/assetmgr/utils.py index f51f5ebef..cf98346f4 100644 --- a/mediathread/assetmgr/utils.py +++ b/mediathread/assetmgr/utils.py @@ -63,7 +63,7 @@ def convert_heic_to_jpg( * Upload jpeg to S3 * Return new url """ - response = requests.get(url, stream=True) + response = requests.get(url, stream=True, timeout=60) # Sort out the new filename parsed_url = urlparse(url) diff --git a/mediathread/assetmgr/views.py b/mediathread/assetmgr/views.py index acd476f8c..4f6ec143e 100644 --- a/mediathread/assetmgr/views.py +++ b/mediathread/assetmgr/views.py @@ -724,7 +724,8 @@ def parse_annotations(self, data, n): username = data['annotations'][n]['author']['username'] author_user = User.objects.get(username=username) author_email = author_user.email - hash_or_username = hashlib.sha1(smart_bytes(author_email)).hexdigest() + hash_or_username = hashlib.sha1( + smart_bytes(author_email), usedforsecurity=False).hexdigest() user_node['http://xmlns.com/foaf/0.1/name'] = [{"value": data.get( 'annotations')[n]['author']['public_name'], "type": "literal"}] diff --git a/mediathread/main/util.py b/mediathread/main/util.py index e94a1d92d..68b2ff4e7 100644 --- a/mediathread/main/util.py +++ b/mediathread/main/util.py @@ -60,6 +60,7 @@ def make_pmt_item(data): raise ImproperlyConfigured try: - return requests.post(TASK_ASSIGNMENT_DESTINATION, data=data) + return requests.post( + TASK_ASSIGNMENT_DESTINATION, data=data, timeout=60) except SSLError as e: capture_exception(e) diff --git a/mediathread/main/views.py b/mediathread/main/views.py index 83ef67aba..a1f954562 100644 --- a/mediathread/main/views.py +++ b/mediathread/main/views.py @@ -519,7 +519,7 @@ def delete_uploaded_media(self, url, secret, asset): 'redirect_url': redirect_to, 'nonce': nonce, 'hmac': digest - }) + }, timeout=60) return response.status_code == 200 def form_valid(self, form): @@ -610,7 +610,7 @@ def convert_media(self, user, course, url, secret, asset, folder): 'folder': folder, 'audio': asset.primary.is_audio(), 'set_course': course.group.name - }) + }, timeout=60) return response.status_code == 200 def convert_course_media(self, user, course, url, secret, folder): diff --git a/requirements.txt b/requirements.txt index 69eaed47f..02ce1b475 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ flake8==7.1.0 lxml==5.3.0 extras==1.0.0 fixtures==4.2.2 -pbr>=0.11 +pbr==6.1.0 six==1.17.0 sqlparse==0.5.3 # django-debug-toolbar @@ -75,9 +75,6 @@ django-impersonate==1.9.2 django-registration-redux==2.13 django-cors-headers==4.6.0 -# Django >= 3.1 has full support for samesite cookies. -# Until then, we'll need to use this. - httplib2==0.22.0 oauth==1.0.1 oauth2==1.9.0.post1 @@ -130,7 +127,8 @@ zeep==4.3.1 stevedore==5.4.0 pyyaml==6.0.2 -bandit==1.7.0 +rich==13.9.2 # bandit +bandit==1.7.10 funcsigs==1.0.2 pypanopto==0.2.0 entrypoints==0.4 @@ -154,6 +152,7 @@ pi-heif==0.21.0 # memcached requirements/src/pylibmc-1.7.0.dev0-cp312-cp312-linux_x86_64.whl;sys_platform == "linux" and python_version=="3.12" requirements/src/pylibmc-1.7.0.dev0-cp313-cp313-linux_x86_64.whl;sys_platform == "linux" and python_version=="3.13" + requests-file==2.1.0 typing_extensions==4.12.0 pyparsing==3.2.0