@@ -513,6 +513,56 @@ async def test_resolve_agent_card_from_url_invalid_url(self):
513513 with pytest .raises (AgentCardResolutionError , match = "Invalid URL format" ):
514514 await agent ._resolve_agent_card_from_url ("invalid-url" , Mock ())
515515
516+ @pytest .mark .asyncio
517+ async def test_resolve_agent_card_rejects_plain_http_source (self ):
518+ """A cleartext card source is refused before the credential is attached."""
519+
520+ async def provider (ctx ):
521+ return A2aCardRequestConfig (headers = {"Authorization" : "Bearer abc" })
522+
523+ agent = RemoteA2aAgent (
524+ name = "test_agent" ,
525+ agent_card = "http://example.com/agent.json" ,
526+ config = A2aRemoteAgentConfig (
527+ card_request_interceptors = [
528+ CardRequestInterceptor (before_request = provider )
529+ ]
530+ ),
531+ )
532+
533+ with patch .object (agent , "_ensure_httpx_client" ) as mock_ensure_client :
534+ mock_ensure_client .return_value = AsyncMock ()
535+ with patch (
536+ "google.adk.agents.remote_a2a_agent.A2ACardResolver"
537+ ) as mock_resolver_class :
538+ mock_resolver = AsyncMock ()
539+ mock_resolver .get_agent_card .return_value = self .agent_card
540+ mock_resolver_class .return_value = mock_resolver
541+
542+ with pytest .raises (AgentCardResolutionError , match = "must use https" ):
543+ await agent ._resolve_agent_card (Mock ())
544+
545+ # No fetch was attempted, so the credential never went out over cleartext.
546+ mock_resolver_class .assert_not_called ()
547+
548+ @pytest .mark .asyncio
549+ async def test_resolve_agent_card_allows_loopback_http_source (self ):
550+ """Plain http stays allowed for the local-development card source."""
551+ agent = RemoteA2aAgent (
552+ name = "test_agent" , agent_card = "http://localhost:8000/agent.json"
553+ )
554+
555+ with patch .object (agent , "_ensure_httpx_client" ) as mock_ensure_client :
556+ mock_ensure_client .return_value = AsyncMock ()
557+ with patch (
558+ "google.adk.agents.remote_a2a_agent.A2ACardResolver"
559+ ) as mock_resolver_class :
560+ mock_resolver = AsyncMock ()
561+ mock_resolver .get_agent_card .return_value = self .agent_card
562+ mock_resolver_class .return_value = mock_resolver
563+
564+ assert await agent ._resolve_agent_card (Mock ()) == self .agent_card
565+
516566 @pytest .mark .asyncio
517567 async def test_card_request_interceptors_injects_headers (self ):
518568 """Header provider headers (from session state) are sent for the card."""
0 commit comments