Skip to content

Commit

Permalink
test: avoid RE vulnerability in unit tests (#249)
Browse files Browse the repository at this point in the history
Signed-off-by: Phil Adams <phil_adams@us.ibm.com>
  • Loading branch information
padamstx authored Mar 14, 2024
1 parent d82b910 commit 8ddcf7f
Show file tree
Hide file tree
Showing 22 changed files with 438 additions and 1,288 deletions.
10 changes: 5 additions & 5 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "^.secrets.baseline$",
"lines": null
},
"generated_at": "2024-02-15T21:11:11Z",
"generated_at": "2024-03-14T17:02:35Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -184,7 +184,7 @@
"hashed_secret": "b8473b86d4c2072ca9b08bd28e373e8253e865c4",
"is_secret": false,
"is_verified": false,
"line_number": 5675,
"line_number": 5211,
"type": "Secret Keyword",
"verified_result": null
}
Expand All @@ -194,23 +194,23 @@
"hashed_secret": "f0b0b291c4d22d76db59faaeb94802714dd6d884",
"is_secret": false,
"is_verified": false,
"line_number": 871,
"line_number": 1000,
"type": "Hex High Entropy String",
"verified_result": null
},
{
"hashed_secret": "4c41e7a08e8895da0c6066adf33bf389c202b4e2",
"is_secret": false,
"is_verified": false,
"line_number": 1284,
"line_number": 1414,
"type": "Hex High Entropy String",
"verified_result": null
},
{
"hashed_secret": "ca8b3e9d1445b3218e3512da63b05c8f26f181e5",
"is_secret": false,
"is_verified": false,
"line_number": 1293,
"line_number": 1423,
"type": "Hex High Entropy String",
"verified_result": null
}
Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_case_management_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
1,084 changes: 195 additions & 889 deletions test/unit/test_catalog_management_v1.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion test/unit/test_context_based_restrictions_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def preprocess_url(operation_path: str):
# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing
# /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_enterprise_billing_units_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_enterprise_management_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_enterprise_usage_reports_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
238 changes: 72 additions & 166 deletions test/unit/test_global_catalog_v1.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion test/unit/test_global_search_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_global_tagging_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_iam_access_groups_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_iam_identity_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_iam_policy_management_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def preprocess_url(operation_path: str):

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if re.fullmatch('.*/+', request_url) is None:
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')

Expand Down
50 changes: 30 additions & 20 deletions test/unit/test_ibm_cloud_shell_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@
_base_url = 'https://api.shell.cloud.ibm.com'
_service.set_service_url(_base_url)


def preprocess_url(operation_path: str):
"""
Returns the request url associated with the specified operation path.
This will be base_url concatenated with a quoted version of operation_path.
The returned request URL is used to register the mock response so it needs
to match the request URL that is formed by the requests library.
"""
# First, unquote the path since it might have some quoted/escaped characters in it
# due to how the generator inserts the operation paths into the unit test code.
operation_path = urllib.parse.unquote(operation_path)

# Next, quote the path using urllib so that we approximate what will
# happen during request processing.
operation_path = urllib.parse.quote(operation_path, safe='/')

# Finally, form the request URL from the base URL and operation path.
request_url = _base_url + operation_path

# If the request url does NOT end with a /, then just return it as-is.
# Otherwise, return a regular expression that matches one or more trailing /.
if not request_url.endswith('/'):
return request_url
return re.compile(request_url.rstrip('/') + '/+')


##############################################################################
# Start of Service: AccountSettings
##############################################################################
Expand All @@ -43,21 +69,13 @@ class TestGetAccountSettings:
Test Class for get_account_settings
"""

def preprocess_url(self, request_url: str):
"""
Preprocess the request URL to ensure the mock response will be found.
"""
if re.fullmatch('.*/+', request_url) is None:
return request_url
return re.compile(request_url.rstrip('/') + '/+')

@responses.activate
def test_get_account_settings_all_params(self):
"""
get_account_settings()
"""
# Set up mock
url = self.preprocess_url(_base_url + '/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
url = preprocess_url('/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
mock_response = '{"_id": "id", "_rev": "rev", "account_id": "account_id", "created_at": 10, "created_by": "created_by", "default_enable_new_features": false, "default_enable_new_regions": true, "enabled": false, "features": [{"enabled": false, "key": "key"}], "regions": [{"enabled": false, "key": "key"}], "type": "type", "updated_at": 10, "updated_by": "updated_by"}'
responses.add(responses.GET, url, body=mock_response, content_type='application/json', status=200)

Expand All @@ -77,7 +95,7 @@ def test_get_account_settings_value_error(self):
test_get_account_settings_value_error()
"""
# Set up mock
url = self.preprocess_url(_base_url + '/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
url = preprocess_url('/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
mock_response = '{"_id": "id", "_rev": "rev", "account_id": "account_id", "created_at": 10, "created_by": "created_by", "default_enable_new_features": false, "default_enable_new_regions": true, "enabled": false, "features": [{"enabled": false, "key": "key"}], "regions": [{"enabled": false, "key": "key"}], "type": "type", "updated_at": 10, "updated_by": "updated_by"}'
responses.add(responses.GET, url, body=mock_response, content_type='application/json', status=200)

Expand All @@ -99,21 +117,13 @@ class TestUpdateAccountSettings:
Test Class for update_account_settings
"""

def preprocess_url(self, request_url: str):
"""
Preprocess the request URL to ensure the mock response will be found.
"""
if re.fullmatch('.*/+', request_url) is None:
return request_url
return re.compile(request_url.rstrip('/') + '/+')

@responses.activate
def test_update_account_settings_all_params(self):
"""
update_account_settings()
"""
# Set up mock
url = self.preprocess_url(_base_url + '/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
url = preprocess_url('/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
mock_response = '{"_id": "id", "_rev": "rev", "account_id": "account_id", "created_at": 10, "created_by": "created_by", "default_enable_new_features": false, "default_enable_new_regions": true, "enabled": false, "features": [{"enabled": false, "key": "key"}], "regions": [{"enabled": false, "key": "key"}], "type": "type", "updated_at": 10, "updated_by": "updated_by"}'
responses.add(responses.POST, url, body=mock_response, content_type='application/json', status=200)

Expand Down Expand Up @@ -184,7 +194,7 @@ def test_update_account_settings_value_error(self):
test_update_account_settings_value_error()
"""
# Set up mock
url = self.preprocess_url(_base_url + '/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
url = preprocess_url('/api/v1/user/accounts/12345678-abcd-1a2b-a1b2-1234567890ab/settings')
mock_response = '{"_id": "id", "_rev": "rev", "account_id": "account_id", "created_at": 10, "created_by": "created_by", "default_enable_new_features": false, "default_enable_new_regions": true, "enabled": false, "features": [{"enabled": false, "key": "key"}], "regions": [{"enabled": false, "key": "key"}], "type": "type", "updated_at": 10, "updated_by": "updated_by"}'
responses.add(responses.POST, url, body=mock_response, content_type='application/json', status=200)

Expand Down
Loading

0 comments on commit 8ddcf7f

Please sign in to comment.