feat(core): harden anti-ssrf#35960
Conversation
Merging this PR will improve performance by 35.4%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | test_import_time[LangChainTracer] |
476.6 ms | 426.7 ms | +11.7% |
| ⚡ | WallTime | test_async_callbacks_in_sync |
25.1 ms | 18.5 ms | +35.4% |
| ⚡ | WallTime | test_import_time[HumanMessage] |
269.5 ms | 242 ms | +11.37% |
| ⚡ | WallTime | test_import_time[PydanticOutputParser] |
557.4 ms | 492.7 ms | +13.13% |
| ⚡ | WallTime | test_import_time[InMemoryRateLimiter] |
177.2 ms | 160.4 ms | +10.42% |
| ⚡ | WallTime | test_import_time[CallbackManager] |
327.4 ms | 290 ms | +12.93% |
| ⚡ | WallTime | test_import_time[BaseChatModel] |
554.8 ms | 489.1 ms | +13.42% |
| ⚡ | WallTime | test_import_time[Document] |
191.9 ms | 174.3 ms | +10.11% |
| ⚡ | WallTime | test_import_time[Runnable] |
510.1 ms | 454.5 ms | +12.24% |
| ⚡ | WallTime | test_import_time[ChatPromptTemplate] |
655.9 ms | 566.2 ms | +15.84% |
| ⚡ | WallTime | test_import_time[tool] |
561.3 ms | 490 ms | +14.55% |
Comparing eugene/harden_ssrf (e65d0cd) with master (1d2916b)
Footnotes
-
23 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
Additional
|
| IP | Provider | Service |
|---|---|---|
169.254.170.23 |
AWS | EKS Pod Identity Agent |
fd00:ec2::254 |
AWS | EC2 IMDSv2 over IPv6 (Nitro instances) |
fd00:ec2::23 |
AWS | EKS Pod Identity Agent (IPv6) |
fe80::a9fe:a9fe |
OpenStack | Nova metadata (IPv6 link-local equiv of 169.254.169.254) |
Suggested fix
Rather than enumerating every 169.254.x.x address individually, block the entire link-local range in is_cloud_metadata. This covers all current entries and any future provider using this range:
CLOUD_METADATA_RANGES = [
ipaddress.ip_network("169.254.0.0/16"),
]
# Add IPv6 metadata endpoints not covered by the range:
CLOUD_METADATA_IPS = [
"169.254.169.254", # AWS EC2/ECS, Azure VM, GCP, DigitalOcean, OCI, Hetzner, Vultr, Linode
"169.254.170.2", # AWS ECS task credential endpoint
"169.254.170.23", # AWS EKS Pod Identity Agent
"100.100.100.200", # Alibaba Cloud / Aliyun ECS (CGNAT range, not link-local)
"fd00:ec2::254", # AWS EC2 IMDSv2 over IPv6 (Nitro instances)
"fd00:ec2::23", # AWS EKS Pod Identity Agent (IPv6)
"fe80::a9fe:a9fe", # OpenStack Nova metadata (IPv6 link-local equiv of 169.254.169.254)
]
def is_cloud_metadata(hostname: str, ip_str: str | None = None) -> bool:
if hostname.lower() in CLOUD_METADATA_HOSTNAMES:
return True
if ip_str:
try:
if ip_str in CLOUD_METADATA_IPS:
return True
ip = ipaddress.ip_address(ip_str)
if any(ip in r for r in CLOUD_METADATA_RANGES):
return True
except ValueError:
pass
return FalseTested all cases — 11/11 pass including arbitrary 169.254.x.x addresses, the new IPv6 endpoints, and confirming RFC1918 private IPs (10.x, 192.168.x) are correctly not flagged as cloud metadata.
harden anti-ssrf