Skip to content

fix(acp): forward allowlisted client headers on all ACP paths - #384

Merged
rehmanmuradali merged 2 commits into
mainfrom
fix/acp-forward-client-headers
Aug 3, 2026
Merged

fix(acp): forward allowlisted client headers on all ACP paths#384
rehmanmuradali merged 2 commits into
mainfrom
fix/acp-forward-client-headers

Conversation

@rehmanmuradali

@rehmanmuradali rehmanmuradali commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • get_headers(agent) is called from several ACP paths (send_message_stream, create_task, cancel/interrupt) without threading the inbound client headers.
  • As a result filter_request_headers(None) returned {}, so no allowlisted client x-* headers ever reached the agent.
  • Fall back to the inbound request headers when callers don't pass them, so the existing allowlist actually forwards them.

Test plan

  • Trigger an ACP path that previously dropped headers (e.g. send_message_stream) and confirm allowlisted client x-* headers now reach the agent.
  • Confirm existing behavior is preserved when request_headers is explicitly passed.

Made with Cursor

Greptile Summary

This PR fixes a bug where allowlisted x-* client headers were never forwarded to the agent on most ACP paths because get_headers() received request_headers=None and filter_request_headers(None) returned {}. The fix adds a four-line fallback that reads self._request.headers when no headers are explicitly passed, consistent with how get_delegation_headers() already reads the same source.

  • get_headers() now falls back to dict(self._request.headers) when request_headers is None; the existing BLOCKED_HEADERS + x-*-allowlist filtering in filter_request_headers() is unchanged, so credentials (authorization, x-api-key, etc.) remain blocked.
  • Callers that pass request_headers={} explicitly opt out of the fallback — the empty dict short-circuits filter_request_headers and no client headers are forwarded.
  • Two new unit tests cover both the fallback path and the explicit-empty-dict opt-out, including assertions that blocked headers (authorization, x-api-key) are not forwarded.

Confidence Score: 5/5

Safe to merge. The change is minimal and scoped to a single fallback in get_headers(); the security-sensitive filtering path (filter_request_headers + BLOCKED_HEADERS) is untouched.

The four-line fallback is consistent with how get_delegation_headers() already reads self._request.headers. Credential headers remain blocked by the existing allowlist. The two new tests directly exercise both the fallback and the opt-out paths with correct assertions on sensitive header names.

Files Needing Attention: No files require special attention.

Important Files Changed

Filename Overview
agentex/src/domain/services/agent_acp_service.py Adds a 4-line fallback in get_headers() so inbound x-* client headers are forwarded when callers don't explicitly pass request_headers. Security filtering via filter_request_headers and BLOCKED_HEADERS is unchanged.
agentex/tests/unit/services/test_agent_acp_service.py Adds two new unit tests covering the fallback path (omitted request_headers uses inbound headers) and the explicit empty-dict opt-out path. Both cover the security-critical header filtering cases.

Sequence Diagram

sequenceDiagram
    participant Client
    participant ACPPath as ACP Path
    participant GetHeaders as get_headers
    participant FilterHeaders as filter_request_headers
    participant AgentPod as Agent Pod

    Client->>ACPPath: "HTTP request with x-* headers"
    ACPPath->>GetHeaders: get_headers(agent)

    alt Before fix
        GetHeaders->>FilterHeaders: filter_request_headers(None)
        FilterHeaders-->>GetHeaders: "{} empty dict"
    else After fix
        GetHeaders->>GetHeaders: "request_headers = dict(self._request.headers)"
        GetHeaders->>FilterHeaders: filter_request_headers(inbound headers)
        FilterHeaders-->>GetHeaders: "allowlisted x-* headers only"
    end

    GetHeaders-->>ACPPath: merged headers with delegation + auth + x-request-id
    ACPPath->>AgentPod: JSON-RPC with forwarded allowlisted headers
Loading

Reviews (5): Last reviewed commit: "test(acp): cover get_headers inbound-hea..." | Re-trigger Greptile

Copilot AI review requested due to automatic review settings July 29, 2026 12:19
@rehmanmuradali
rehmanmuradali requested a review from a team as a code owner July 29, 2026 12:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes ACP header propagation by ensuring allowlisted client x-* headers are forwarded to agent ACP servers on ACP paths where get_headers(agent) was previously called without explicit request_headers.

Changes:

  • Add a fallback in AgentACPService.get_headers() to use inbound Request.headers when request_headers is not provided.
  • Preserve existing behavior when request_headers is explicitly passed (including opting out by passing {}).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread agentex/src/domain/services/agent_acp_service.py
@rehmanmuradali
rehmanmuradali marked this pull request as draft July 29, 2026 12:22
@rehmanmuradali
rehmanmuradali marked this pull request as ready for review July 29, 2026 12:26
@rehmanmuradali
rehmanmuradali force-pushed the fix/acp-forward-client-headers branch 2 times, most recently from 775527b to 15e0cbb Compare July 31, 2026 07:56
@rehmanmuradali
rehmanmuradali enabled auto-merge (squash) July 31, 2026 08:02
rehmanmuradali and others added 2 commits August 4, 2026 02:01
Several ACP paths call get_headers(agent) without threading the inbound
client headers, so filter_request_headers(None) returned {} and no
allowlisted client x-* headers reached the agent. Fall back to the
inbound request headers so the existing allowlist forwards them.

Co-authored-by: Cursor <cursoragent@cursor.com>
Assert that omitting request_headers forwards allowlisted inbound x-*
headers (dropping sensitive ones), and that passing {} forwards none.

Co-authored-by: Cursor <cursoragent@cursor.com>
@rehmanmuradali
rehmanmuradali force-pushed the fix/acp-forward-client-headers branch from 15e0cbb to bda8767 Compare August 3, 2026 22:01
@rehmanmuradali
rehmanmuradali merged commit 2c2d5c8 into main Aug 3, 2026
46 checks passed
@rehmanmuradali
rehmanmuradali deleted the fix/acp-forward-client-headers branch August 3, 2026 22:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants