litellm - 💡(How to fix) Fix [Bug]: A2A agent access control bypass - any valid key can invoke agents regardless of Access Group [1 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#25421Fetched 2026-04-10 03:41:12
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
labeled ×1renamed ×1

Error Message

  1. Fail-open on exceptions: _get_allowed_agents_for_key, _get_allowed_agents_for_team, and _get_agents_from_access_groups all have bare except Exception: return []. Any DB error, missing prisma_client, or schema mismatch silently returns an empty list, which is_agent_allowed interprets as "no restrictions" → allows all. This is the wrong fail-safe direction for a security gate — it should deny on error, not allow. No relevant error logs — the permission check silently falls through. Enabling verbose logging may show warnings from agent_permission_handler if exceptions are being swallowed.

Root Cause

The root cause appears to be in agent_permission_handler.py:

Code Example

allowed_agents = await AgentRequestHandler.get_allowed_agents(user_api_key_auth)

# Empty list means no restrictions - allow all
if len(allowed_agents) == 0:
    return True

return agent_id in allowed_agents

---

curl -X POST http://litellm:4000/a2a/my-agent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-key-A" \
  -d '{"jsonrpc":"2.0","id":"1","method":"message/send","params":{"message":{"role":"user","parts":[{"text":"hello"}],"messageId":"abc"}}}'

---

curl -X POST http://litellm:4000/a2a/my-agent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-key-B" \
  -d '{"jsonrpc":"2.0","id":"2","method":"message/send","params":{"message":{"role":"user","parts":[{"text":"hello"}],"messageId":"def"}}}'
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

When using the /a2a/{agent_id} endpoint with Access Groups configured to restrict which keys can invoke an agent, any valid API key can invoke the agent, even keys that are NOT in the assigned Access Group.

Expected: Only keys belonging to the Access Group assigned to the agent (or keys with direct agent access) should be able to call /a2a/{agent_id}. Keys outside the group should receive a 403.

Actual: Any valid API key can invoke any agent. Without an Authorization header it correctly returns 401, so authentication works — but authorization (access group enforcement) does not.

The root cause appears to be in agent_permission_handler.py:

allowed_agents = await AgentRequestHandler.get_allowed_agents(user_api_key_auth)

# Empty list means no restrictions - allow all
if len(allowed_agents) == 0:
    return True

return agent_id in allowed_agents

This has two problems:

  1. Bi-directional config required but not documented: get_allowed_agents resolves agents from the key's object_permission and access_group_ids. If the key doesn't have these fields set (only the agent has the group assigned), get_allowed_agents returns [] → treated as "no restrictions" → allows all. The docs at https://docs.litellm.ai/docs/a2a_agent_permissions imply that assigning an agent to an Access Group is sufficient, but the key side must also declare group membership.

  2. Fail-open on exceptions: _get_allowed_agents_for_key, _get_allowed_agents_for_team, and _get_agents_from_access_groups all have bare except Exception: return []. Any DB error, missing prisma_client, or schema mismatch silently returns an empty list, which is_agent_allowed interprets as "no restrictions" → allows all. This is the wrong fail-safe direction for a security gate — it should deny on error, not allow.

Steps to Reproduce

  1. Create an agent via UI or API (not marked as public)
  2. Create an Access Group (e.g. agent-users)
  3. Assign the agent to the Access Group
  4. Create API Key A — add it to the agent-users Access Group
  5. Create API Key B — do NOT add it to any Access Group
  6. Call the agent with Key A:
curl -X POST http://litellm:4000/a2a/my-agent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-key-A" \
  -d '{"jsonrpc":"2.0","id":"1","method":"message/send","params":{"message":{"role":"user","parts":[{"text":"hello"}],"messageId":"abc"}}}'
  1. Call the agent with Key B (should be denied, but is allowed):
curl -X POST http://litellm:4000/a2a/my-agent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-key-B" \
  -d '{"jsonrpc":"2.0","id":"2","method":"message/send","params":{"message":{"role":"user","parts":[{"text":"hello"}],"messageId":"def"}}}'
  1. Both requests succeed with 200. Key B should receive 403.

Relevant log output

No relevant error logs — the permission check silently falls through. Enabling verbose logging may show warnings from agent_permission_handler if exceptions are being swallowed.

What part of LiteLLM is this about?

Proxy

What LiteLLM version are you on?

v1.82.6

Twitter / LinkedIn details

No response

extent analysis

TL;DR

To fix the issue, update the agent_permission_handler.py to handle exceptions correctly and ensure bi-directional configuration is properly documented and implemented.

Guidance

  • Review the agent_permission_handler.py file and update the exception handling in _get_allowed_agents_for_key, _get_allowed_agents_for_team, and _get_agents_from_access_groups to deny access on error instead of allowing all.
  • Ensure that the documentation at https://docs.litellm.ai/docs/a2a_agent_permissions is updated to reflect the requirement for bi-directional configuration, where both the agent and the key must be configured with the Access Group.
  • Verify that the object_permission and access_group_ids fields are properly set for the API keys and agents.
  • Test the updated configuration with the steps provided in the issue to ensure that only authorized keys can invoke the agent.

Example

try:
    # existing code
except Exception as e:
    # log the error and deny access
    logging.error(f"Error getting allowed agents: {e}")
    return False

Notes

The provided fix assumes that the issue is solely related to the agent_permission_handler.py file and the bi-directional configuration requirement. However, it is possible that there are other factors at play, and additional debugging may be necessary to fully resolve the issue.

Recommendation

Apply the workaround by updating the agent_permission_handler.py file to handle exceptions correctly and ensuring bi-directional configuration is properly implemented. This is because the current implementation has a security vulnerability that allows any valid API key to invoke an agent, even if they are not in the assigned Access Group.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING