Skip to content

Commit a7063fe

Browse files
committed
feat: update code
1 parent c6895e8 commit a7063fe

1 file changed

Lines changed: 87 additions & 3 deletions

File tree

base/src/main/java/com/tinyengine/it/mcp/utils/UrlValidateUtil.java

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ public UrlValidateUtil(OpenAIConfig config) {
1919

2020

2121
public void validateFinalUrl(String finalUrl) {
22-
if (finalUrl == null || finalUrl.isBlank()) {
23-
throw new ServiceException("400", "Invalid baseUrl: empty url");
22+
if(finalUrl == null || finalUrl.isEmpty()) {
23+
throw new ServiceException("400", "baseUrl cannot be null or empty");
2424
}
2525

2626
URI uri;
@@ -44,6 +44,7 @@ public void validateFinalUrl(String finalUrl) {
4444
throw new ServiceException("500", "No AI allowed hosts configured");
4545
}
4646

47+
enforceHttpsAndIpCheck(uri, host);
4748
return;
4849
}
4950

@@ -55,14 +56,97 @@ public void validateFinalUrl(String finalUrl) {
5556
}
5657

5758
if (isLoopback) {
58-
throw new ServiceException("400", "Loopback addresses are not allowed for baseUrl");
59+
throw new ServiceException("400", "Loopback addresses are not allowed for custom baseUrl");
5960
}
6061

62+
enforceHttpsAndIpCheck(uri, host);
6163
}
6264

65+
void enforceHttpsAndIpCheck(URI uri, String host) {
66+
String scheme = uri.getScheme();
67+
if (scheme == null || !"https".equalsIgnoreCase(scheme)) {
68+
throw new ServiceException("400", "Only HTTPS protocol is allowed for custom baseUrl");
69+
}
70+
71+
try {
72+
InetAddress[] addresses = resolveHostAddresses(host);
73+
boolean hasBlockedAddress = Arrays.stream(addresses).anyMatch(this::isBlockedAddress);
74+
if (hasBlockedAddress) {
75+
throw new ServiceException("400", "Internal network addresses are not allowed");
76+
}
77+
} catch (UnknownHostException e) {
78+
throw new ServiceException("400", "Unable to resolve host: " + host);
79+
}
80+
}
81+
82+
InetAddress[] resolveHostAddresses(String host) throws UnknownHostException {
83+
return InetAddress.getAllByName(host);
84+
}
85+
86+
boolean isBlockedAddress(InetAddress address) {
87+
if (address.isLoopbackAddress()
88+
|| address.isSiteLocalAddress()
89+
|| address.isLinkLocalAddress()
90+
|| address.isAnyLocalAddress()
91+
|| address.isMulticastAddress()) {
92+
return true;
93+
}
94+
95+
if (address instanceof Inet4Address) {
96+
return isBlockedIpv4((Inet4Address) address);
97+
}
98+
if (address instanceof Inet6Address) {
99+
return isBlockedIpv6((Inet6Address) address);
100+
}
101+
return false;
102+
}
63103

104+
private boolean isBlockedIpv4(Inet4Address address) {
105+
byte[] octets = address.getAddress();
106+
int first = octets[0] & 0xFF;
107+
int second = octets[1] & 0xFF;
108+
int third = octets[2] & 0xFF;
64109

110+
if (first == 0) {
111+
return true;
112+
}
113+
if (first == 100 && second >= 64 && second <= 127) {
114+
return true;
115+
}
116+
if (first == 192 && second == 0 && third == 0) {
117+
return true;
118+
}
119+
if (first == 192 && second == 0 && third == 2) {
120+
return true;
121+
}
122+
if (first == 198 && (second == 18 || second == 19)) {
123+
return true;
124+
}
125+
if (first == 198 && second == 51 && third == 100) {
126+
return true;
127+
}
128+
if (first == 203 && second == 0 && third == 113) {
129+
return true;
130+
}
131+
return first >= 240;
132+
}
65133

134+
private boolean isBlockedIpv6(Inet6Address address) {
135+
byte[] octets = address.getAddress();
136+
int first = octets[0] & 0xFF;
137+
int second = octets[1] & 0xFF;
66138

139+
if ((first & 0xFE) == 0xFC) {
140+
return true;
141+
}
142+
if (first == 0x20 && second == 0x01) {
143+
int third = octets[2] & 0xFF;
144+
int fourth = octets[3] & 0xFF;
145+
if (third == 0x0D && fourth == 0xB8) {
146+
return true;
147+
}
148+
}
149+
return first == 0xFF;
150+
}
67151

68152
}

0 commit comments

Comments
 (0)