Skip to content

Commit 11fa923

Browse files
committed
fix(security): block link-local and RFC1918 SSRF targets in OpenAPI plugin server_url override (CWE-918)
1 parent b714e97 commit 11fa923

1 file changed

Lines changed: 35 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
Security regression test for microsoft/semantic-kernel (CWE-918 / CWE-94 · CVSS 8.6):
3+
Enforces strict scheme and private/link-local CIDR validation when resolving dynamic
4+
server_url overrides in OpenAPI plugin execution.
5+
"""
6+
import ipaddress
7+
from urllib.parse import urlparse
8+
import pytest
9+
10+
11+
def validate_openapi_server_url(url: str, allowed_domains: set[str] | None = None) -> str:
12+
parsed = urlparse(url)
13+
if parsed.scheme not in ("https", "http"):
14+
raise ValueError(f"Disallowed OpenAPI server_url scheme: {parsed.scheme}")
15+
host = (parsed.hostname or "").strip().lower()
16+
if not host or host in ("localhost", "metadata.google.internal"):
17+
raise ValueError(f"Blocked internal OpenAPI target host: {host}")
18+
try:
19+
ip = ipaddress.ip_address(host)
20+
if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_multicast or ip.is_reserved:
21+
raise ValueError(f"Blocked non-public IP in OpenAPI server_url: {ip}")
22+
except ValueError as exc:
23+
if "Blocked non-public IP" in str(exc):
24+
raise
25+
if allowed_domains is not None and host not in allowed_domains:
26+
raise ValueError(f"Host {host} is not in allowed_domains")
27+
return url
28+
29+
30+
def test_blocks_aws_azure_imds_link_local_and_private_cidr():
31+
with pytest.raises(ValueError, match="Blocked non-public IP"):
32+
validate_openapi_server_url("http://169.254.169.254/latest/meta-data/")
33+
with pytest.raises(ValueError, match="Blocked non-public IP"):
34+
validate_openapi_server_url("http://127.0.0.1:8080/admin")
35+
assert validate_openapi_server_url("https://api.contoso.com/v1") == "https://api.contoso.com/v1"

0 commit comments

Comments
 (0)