diff --git a/pyrit/backend/mappers/attack_mappers.py b/pyrit/backend/mappers/attack_mappers.py index 64421f8cc8..fd856791a9 100644 --- a/pyrit/backend/mappers/attack_mappers.py +++ b/pyrit/backend/mappers/attack_mappers.py @@ -67,8 +67,8 @@ def _is_azure_blob_url(value: str) -> bool: # Azure Blob Storage enforces HTTPS; rejecting HTTP also limits SSRF surface. if parsed.scheme != "https": return False - host = parsed.netloc.split(":")[0] # strip port - return host.endswith(".blob.core.windows.net") and bool(host.split(".")[0]) + host = parsed.hostname + return bool(host) and host.endswith(".blob.core.windows.net") and bool(host.split(".")[0]) async def _get_sas_for_container_async(*, container_url: str) -> str: diff --git a/tests/unit/backend/test_mappers.py b/tests/unit/backend/test_mappers.py index dd672d594f..2e51604025 100644 --- a/tests/unit/backend/test_mappers.py +++ b/tests/unit/backend/test_mappers.py @@ -820,6 +820,11 @@ def test_data_uri_not_detected(self) -> None: def test_local_path_not_detected(self) -> None: assert _is_azure_blob_url("/tmp/test.png") is False + def test_userinfo_spoofed_host_not_detected(self) -> None: + # The real host is 127.0.0.1; the blob-looking segment is userinfo and must + # not be treated as the host (SSRF bypass regression test). + assert _is_azure_blob_url("https://a.blob.core.windows.net:80@127.0.0.1:6666") is False + class TestSignBlobUrlAsync: """Tests for _sign_blob_url_async helper."""