@@ -22,6 +22,140 @@ class PingStatus(str, Enum):
2222CUSTOM_HEADER_PREFIX = "X-Amzn-Bedrock-AgentCore-Runtime-Custom-"
2323AGENTCORE_RUNTIME_URL_ENV = "AGENTCORE_RUNTIME_URL"
2424
25+ # Headers that cannot be forwarded to agent code.
26+ # Source: https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-header-allowlist.html
27+ RESTRICTED_HEADERS : frozenset [str ] = frozenset (
28+ h .lower ()
29+ for h in [
30+ # Authentication & Authorization
31+ "Proxy-Authorization" ,
32+ "WWW-Authenticate" ,
33+ # Content Negotiation
34+ "Accept" ,
35+ "Accept-Charset" ,
36+ "Accept-Encoding" ,
37+ "Accept-Language" ,
38+ "Content-Type" ,
39+ "Content-Length" ,
40+ "Content-Encoding" ,
41+ "Content-Language" ,
42+ "Content-Location" ,
43+ "Content-Range" ,
44+ # Caching
45+ "Cache-Control" ,
46+ "ETag" ,
47+ "Expires" ,
48+ "If-Match" ,
49+ "If-Modified-Since" ,
50+ "If-None-Match" ,
51+ "If-Range" ,
52+ "If-Unmodified-Since" ,
53+ "Last-Modified" ,
54+ "Pragma" ,
55+ "Vary" ,
56+ # Connection Management
57+ "Connection" ,
58+ "Keep-Alive" ,
59+ "Proxy-Connection" ,
60+ "Upgrade" ,
61+ # Request Context
62+ "Host" ,
63+ "User-Agent" ,
64+ "Referer" ,
65+ "From" ,
66+ # Range / Transfer
67+ "Range" ,
68+ "Accept-Ranges" ,
69+ "Transfer-Encoding" ,
70+ "TE" ,
71+ "Trailer" ,
72+ # Server Information
73+ "Server" ,
74+ "Date" ,
75+ "Location" ,
76+ "Retry-After" ,
77+ # Cookies
78+ "Set-Cookie" ,
79+ "Cookie" ,
80+ # Security
81+ "Content-Security-Policy" ,
82+ "Content-Security-Policy-Report-Only" ,
83+ "Strict-Transport-Security" ,
84+ "X-Content-Type-Options" ,
85+ "X-Frame-Options" ,
86+ "X-XSS-Protection" ,
87+ "Referrer-Policy" ,
88+ "Permissions-Policy" ,
89+ "Cross-Origin-Embedder-Policy" ,
90+ "Cross-Origin-Opener-Policy" ,
91+ "Cross-Origin-Resource-Policy" ,
92+ # CORS
93+ "Access-Control-Allow-Origin" ,
94+ "Access-Control-Allow-Methods" ,
95+ "Access-Control-Allow-Headers" ,
96+ "Access-Control-Allow-Credentials" ,
97+ "Access-Control-Expose-Headers" ,
98+ "Access-Control-Max-Age" ,
99+ "Access-Control-Request-Method" ,
100+ "Access-Control-Request-Headers" ,
101+ "Origin" ,
102+ # Client Hints
103+ "Accept-CH" ,
104+ "Accept-CH-Lifetime" ,
105+ "DPR" ,
106+ "Width" ,
107+ "Viewport-Width" ,
108+ "Downlink" ,
109+ "ECT" ,
110+ "RTT" ,
111+ "Save-Data" ,
112+ # Experimental / Proposed
113+ "Clear-Site-Data" ,
114+ "Feature-Policy" ,
115+ "Expect-CT" ,
116+ "Public-Key-Pins" ,
117+ "Public-Key-Pins-Report-Only" ,
118+ # Proxy
119+ "Via" ,
120+ "Forwarded" ,
121+ "X-Forwarded-For" ,
122+ "X-Forwarded-Host" ,
123+ "X-Forwarded-Proto" ,
124+ "X-Real-IP" ,
125+ "X-Requested-With" ,
126+ "X-CSRF-Token" ,
127+ # IP Spoofing / URL Manipulation
128+ "True-Client-IP" ,
129+ "X-Client-IP" ,
130+ "X-Cluster-Client-IP" ,
131+ "X-Originating-IP" ,
132+ "X-Source-IP" ,
133+ "X-Original-URL" ,
134+ "X-Original-Host" ,
135+ "X-Rewrite-URL" ,
136+ # CDN / Proxy
137+ "CF-Ray" ,
138+ "CF-Connecting-IP" ,
139+ "X-Amz-Cf-Id" ,
140+ "X-Cache" ,
141+ "X-Served-By" ,
142+ # HTTP/2 Pseudo Headers
143+ ":method" ,
144+ ":path" ,
145+ ":scheme" ,
146+ ":authority" ,
147+ ":status" ,
148+ # Server Push
149+ "Link" ,
150+ # WebSocket
151+ "Sec-WebSocket-Key" ,
152+ "Sec-WebSocket-Accept" ,
153+ "Sec-WebSocket-Version" ,
154+ "Sec-WebSocket-Protocol" ,
155+ "Sec-WebSocket-Extensions" ,
156+ ]
157+ )
158+
25159# Baggage keys for routing experiment span attributes
26160BAGGAGE_KEY_EXPERIMENT_ARN = "aws.agentcore.gateway.routing_experiment_arn"
27161BAGGAGE_KEY_EXPERIMENT_VARIANT = "aws.agentcore.gateway.routing_experiment_variant_name"
@@ -32,3 +166,26 @@ class PingStatus(str, Enum):
32166TASK_ACTION_FORCE_HEALTHY = "force_healthy"
33167TASK_ACTION_FORCE_BUSY = "force_busy"
34168TASK_ACTION_CLEAR_FORCED_STATUS = "clear_forced_status"
169+
170+
171+ _CUSTOM_HEADER_PREFIX_LOWER = CUSTOM_HEADER_PREFIX .lower ()
172+ _AUTHORIZATION_HEADER_LOWER = AUTHORIZATION_HEADER .lower ()
173+
174+
175+ def is_forwardable_header (header_name : str ) -> bool :
176+ """Return True if the header may be forwarded to agent code.
177+
178+ Rules (from the AgentCore runtime header allowlist docs):
179+ - Not in the restricted headers list
180+ - Does not start with ``x-amz-`` (reserved for AWS SigV4 signing)
181+ - Does not start with ``x-amzn-`` unless it starts with the legacy
182+ ``X-Amzn-Bedrock-AgentCore-Runtime-Custom-`` prefix
183+ """
184+ lower = header_name .lower ()
185+ if lower in RESTRICTED_HEADERS :
186+ return False
187+ if lower .startswith ("x-amz-" ):
188+ return False
189+ if lower .startswith ("x-amzn-" ) and not lower .startswith (_CUSTOM_HEADER_PREFIX_LOWER ):
190+ return False
191+ return True
0 commit comments