google / google/adk-python

RemoteA2aAgent enforces HTTPS for agent cards, blocking plaintext A2A inside a service mesh (mTLS)

Abierto
#7,139 2 comentarios 0 reacciones 1 asignado Reclamado por @surajksharma07 Ver en GitHub
request clarification
Lenguaje dominante
Python
Estrellas
21.5k
Forks
4k
Merge medio
1 d 14 h
PR fusionados (30 d)
37

Descripción

### What happened

`RemoteA2aAgent` enforces that an agent card's URL — and every RPC target URL inside the resolved card — must be `https`, unless the host is loopback. This is enforced client-side in `src/google/adk/agents/remote_a2a_agent.py` (ADK `2.9.1`):

- `_resolve_agent_card()` rejects a non-loopback `http://` **card source URL** with:
> `Agent card URL must use https, or http on a loopback host: `
- `_validate_card_rpc_targets()` rejects a resolved card whose **RPC target URLs** are non-loopback `http://` with:
> `Agent card RPC URL must use https, or http on a loopback host: `

(`_is_loopback_host()` only permits `localhost`, `*.localhost`, and loopback IPs.) There doesn't appear to be an opt-out (flag, config field, or env var).

### Why this is a problem: A2A inside a service mesh (mTLS)

A very common production topology for multi-agent A2A is Kubernetes + a service mesh (Istio / Cloud Service Mesh, Linkerd) with **STRICT mTLS**. In that model:

- The application speaks **plaintext `http://`** to the peer's in-cluster DNS name (e.g. `http://research.agents.svc.cluster.local/a2a/app/...`).
- The **sidecar proxy transparently upgrades every hop to mTLS**, and authorization is enforced by mesh identity (SPIFFE) + `AuthorizationPolicy`.

This is the mesh's entire design: apps stay plaintext, the mesh provides confidentiality + peer authentication. But ADK's client-side gate refuses plaintext to non-loopback hosts, so the **first delegation fails at card resolution** with `AgentCardResolutionError`. The security property the `https` requirement stands in for (no plaintext MITM) is already guaranteed by the mesh — so the gate is redundant here, yet there's no way to say so.

### Minimal repro

```python
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent

# Non-loopback http card URL — realistic in-cluster A2A address behind a mesh.
agent = RemoteA2aAgent(
name="research",
agent_card="http://research.agents.svc.cluster.local/a2a/app/.well-known/agent-card.json",
)
# On first use -> AgentCardResolutionError:
# "Agent card URL must use https, or http on a loopback host: ..."
```

The underlying transport is fine with `http` — only this ADK-level check blocks it.

### Current workaround (and why it's not great)

Passing a **pre-constructed `AgentCard` object** (rather than a URL/file source) skips both checks — `_validate_card_rpc_targets()` returns early when there is no `http(s)` source, and `_resolve_agent_card()` is never called — so the plaintext POST then flows and the mesh wraps it in mTLS. But this forces callers to give up ADK's lazy live-card fetch and hand-build/hard-code the card + RPC URL, which is exactly the discovery ADK otherwise does for you.

### What we'd like to discuss

Would the maintainers be open to an **opt-in** escape hatch so operators who know they're inside a trusted transport (a mesh) can allow non-loopback `http`? A few shapes, from least to most granular:

1. A per-instance flag, e.g. `RemoteA2aAgent(..., allow_insecure_http=True)` (or on `A2aRemoteAgentConfig`), applied to both the card fetch and the RPC-target validation.
2. An env / global toggle (e.g. `ADK_A2A_ALLOW_INSECURE_HTTP=1`) for cluster-wide deployments.
3. A configurable trusted-host / CIDR allowlist that widens the loopback carve-out.

Opt-in (default stays https-only) keeps the secure-by-default behavior while unblocking the mesh use case. Happy to send a PR if you can point me at the preferred shape.

### Environment

- `google-adk` 2.9.1
- Deployment: GKE + Cloud Service Mesh (managed Istio), namespace-wide STRICT `PeerAuthentication`
- A2A over `RemoteA2aAgent` with in-cluster DNS peer URLs

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.