2121import java .io .IOException ;
2222import java .io .InputStream ;
2323import java .net .HttpURLConnection ;
24+ import java .net .Inet4Address ;
2425import java .net .InetAddress ;
2526import java .net .URISyntaxException ;
2627import java .net .URL ;
@@ -240,7 +241,7 @@ private static boolean isAllowedRemoteUrl(URL url) {
240241
241242 try {
242243 InetAddress inetAddress = InetAddress .getByName (host );
243- if (isBlockedAddress (inetAddress )) {
244+ if (isSafe (inetAddress )) {
244245 return false ;
245246 }
246247 } catch (UnknownHostException e ) {
@@ -251,21 +252,6 @@ private static boolean isAllowedRemoteUrl(URL url) {
251252 return ALLOWED_DOMAINS .isEmpty () || isHostInAllowedDomains (host );
252253 }
253254
254- private static boolean isBlockedAddress (InetAddress inetAddress ) {
255- String hostAddress = inetAddress .getHostAddress ();
256- return inetAddress .isAnyLocalAddress ()
257- || inetAddress .isLoopbackAddress ()
258- || inetAddress .isSiteLocalAddress ()
259- || inetAddress .isLinkLocalAddress ()
260- || hostAddress .startsWith ("127." )
261- || hostAddress .equals ("0.0.0.0" )
262- || hostAddress .equals ("::1" )
263- || hostAddress .startsWith ("169.254." )
264- || hostAddress .startsWith ("10." )
265- || hostAddress .startsWith ("172.16." )
266- || hostAddress .startsWith ("192.168." );
267- }
268-
269255 private static boolean isHostInAllowedDomains (String host ) {
270256 return ALLOWED_DOMAINS .stream ()
271257 .anyMatch (allowed -> host .equalsIgnoreCase (allowed ) || host .endsWith ("." + allowed ));
@@ -304,12 +290,58 @@ private static void copyURLToFileSafe(URL url, File destination) throws IOExcept
304290 }
305291
306292 private static HttpURLConnection createConnection (URL url ) throws IOException {
307- HttpURLConnection connection = (HttpURLConnection ) url .openConnection ();
308- connection .setConnectTimeout (CONNECTION_TIMEOUT_MILLIS );
309- connection .setReadTimeout (CONNECTION_TIMEOUT_MILLIS );
310- connection .setInstanceFollowRedirects (false );
311- connection .setRequestMethod ("GET" );
312- return connection ;
293+ InetAddress safeAddress = InetAddress .getByName (url .getHost ());
294+ if (isSafe (safeAddress )) {
295+ HttpURLConnection connection = (HttpURLConnection ) url .openConnection ();
296+ connection .setConnectTimeout (CONNECTION_TIMEOUT_MILLIS );
297+ connection .setReadTimeout (CONNECTION_TIMEOUT_MILLIS );
298+ connection .setInstanceFollowRedirects (false );
299+ connection .setRequestMethod ("GET" );
300+ return connection ;
301+ }
302+ return null ;
303+
304+ }
305+
306+ public static boolean isSafe (InetAddress address ) {
307+ if (address .isLoopbackAddress ())
308+ return false ;
309+
310+ if (address .isSiteLocalAddress ())
311+ return false ;
312+
313+ if (address .isLinkLocalAddress ())
314+ return false ;
315+
316+ if (address .isAnyLocalAddress ())
317+ return false ;
318+
319+ if (address .isMulticastAddress ())
320+ return false ;
321+
322+ if (address instanceof Inet4Address ) {
323+ byte [] addr = address .getAddress ();
324+ int firstOctet = addr [0 ] & 0xFF ;
325+ int secondOctet = addr [1 ] & 0xFF ;
326+
327+ // 10.0.0.0/8
328+ if (firstOctet == 10 )
329+ return false ;
330+
331+ // 172.16.0.0/12
332+ if (firstOctet == 172 && (secondOctet >= 16 && secondOctet <= 31 ))
333+ return false ;
334+
335+ // 192.168.0.0/16
336+ if (firstOctet == 192 && secondOctet == 168 )
337+ return false ;
338+
339+ // 100.64.0.0/10 (CGNAT)
340+ if (firstOctet == 100 && (secondOctet >= 64 && secondOctet <= 127 ))
341+ return false ;
342+ }
343+
344+ return true ;
313345 }
314346
315347 private static boolean isRedirectResponse (int responseCode ) {
0 commit comments