fix(mcp): catch JSONDecodeError in OAuth discovery functions 🤖🤖🤖 (#34868)

This commit is contained in:
Jean Ibarz
2026-04-10 03:28:57 +02:00
committed by GitHub
parent 1117b6e72d
commit d50f096b14
2 changed files with 38 additions and 3 deletions

View File

@ -146,7 +146,7 @@ def discover_protected_resource_metadata(
return ProtectedResourceMetadata.model_validate(response.json())
elif response.status_code == 404:
continue # Try next URL
except (RequestError, ValidationError):
except (RequestError, ValidationError, json.JSONDecodeError):
continue # Try next URL
return None
@ -166,7 +166,7 @@ def discover_oauth_authorization_server_metadata(
return OAuthMetadata.model_validate(response.json())
elif response.status_code == 404:
continue # Try next URL
except (RequestError, ValidationError):
except (RequestError, ValidationError, json.JSONDecodeError):
continue # Try next URL
return None
@ -276,7 +276,7 @@ def check_support_resource_discovery(server_url: str) -> tuple[bool, str]:
else:
return False, ""
return False, ""
except RequestError:
except (RequestError, json.JSONDecodeError, IndexError):
# Not support resource discovery, fall back to well-known OAuth metadata
return False, ""

View File

@ -862,6 +862,15 @@ class TestAuthOrchestration:
result = discover_protected_resource_metadata(None, "https://api.example.com")
assert result is None
# JSONDecodeError (non-JSON 200 response)
mock_get.side_effect = None
bad_json_response = Mock()
bad_json_response.status_code = 200
bad_json_response.json.side_effect = json.JSONDecodeError("Expecting value", "", 0)
mock_get.return_value = bad_json_response
result = discover_protected_resource_metadata(None, "https://api.example.com")
assert result is None
@patch("core.helper.ssrf_proxy.get")
def test_discover_oauth_authorization_server_metadata(self, mock_get):
# Success
@ -892,6 +901,14 @@ class TestAuthOrchestration:
result = discover_oauth_authorization_server_metadata(None, "https://api.example.com")
assert result is None
# JSONDecodeError (non-JSON 200 response)
bad_json_response = Mock()
bad_json_response.status_code = 200
bad_json_response.json.side_effect = json.JSONDecodeError("Expecting value", "", 0)
mock_get.return_value = bad_json_response
result = discover_oauth_authorization_server_metadata(None, "https://api.example.com")
assert result is None
def test_get_effective_scope(self):
prm = ProtectedResourceMetadata(
resource="https://api.example.com",
@ -997,6 +1014,24 @@ class TestAuthOrchestration:
supported, url = check_support_resource_discovery("https://api")
assert supported is False
# Case 6: JSONDecodeError (non-JSON 200 response)
mock_get.side_effect = None
bad_json_res = Mock()
bad_json_res.status_code = 200
bad_json_res.json.side_effect = json.JSONDecodeError("Expecting value", "", 0)
mock_get.return_value = bad_json_res
supported, url = check_support_resource_discovery("https://api")
assert supported is False
assert url == ""
# Case 7: Empty authorization_servers array (IndexError)
empty_res = Mock()
empty_res.status_code = 200
empty_res.json.return_value = {"authorization_servers": []}
mock_get.return_value = empty_res
supported, url = check_support_resource_discovery("https://api")
assert supported is False
def test_discover_oauth_metadata(self):
with patch("core.mcp.auth.auth_flow.discover_protected_resource_metadata") as mock_prm:
with patch("core.mcp.auth.auth_flow.discover_oauth_authorization_server_metadata") as mock_asm: