CVE-2022-4096: Server-Side Request Forgery (SSRF) (CWE-918)
value: Server-Side Request Forgery (SSRF) in GitHub repository appsmithorg/appsmith prior to 1.8.2.
CWE description: The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
CVSS v3 base score: 6.5
Published: 2022-11-21T15:15Z
Repository: https://github.com/appsmithorg/appsmith
Language: Java
Files changed: app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java, app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java, app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java, app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java, app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java
Commit date: 2022-09-19 12:41:57 +0530
Commit message: fix: Better support for disallowed hosts (#16842)


Diff: diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java
index 99987e1ce..2f3556d86 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java
@@ -33,22 +33,19 @@ import reactor.core.publisher.Mono;
 import reactor.netty.http.client.HttpClient;
 import reactor.netty.resources.ConnectionProvider;
 
 import javax.crypto.SecretKey;
 import java.io.IOException;
-import java.net.InetAddress;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.Date;
 import java.util.List;
 import java.util.Set;
 
-import static com.appsmith.external.helpers.restApiUtils.helpers.URIUtils.DISALLOWED_HOSTS;
 import static org.apache.commons.lang3.StringUtils.isNotEmpty;
 
 @NoArgsConstructor
 public class TriggerUtils {
 
@@ -202,18 +199,14 @@ public class TriggerUtils {
                          * In case the redirected URL is not absolute (complete), create the new URL using the relative path
                          * This particular scenario is seen in the URL : https://rickandmortyapi.com/api/character
                          * It redirects to partial URI : /api/character/
                          * In this scenario we should convert the partial URI to complete URI
                          */
-                        URI redirectUri;
+                        final URI redirectUri;
                         try {
                             redirectUri = new URI(redirectUrl);
-                            if (DISALLOWED_HOSTS.contains(redirectUri.getHost())
-                                    || DISALLOWED_HOSTS.contains(InetAddress.getByName(redirectUri.getHost()).getHostAddress())) {
-                                return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, "Host not allowed."));
-                            }
-                        } catch (URISyntaxException | UnknownHostException e) {
+                        } catch (URISyntaxException e) {
                             return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, e));
                         }
 
                         return httpCall(webClient, httpMethod, redirectUri, finalRequestBody, iteration + 1);
                     }
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java
index cc3c761b1..70c9b5af9 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java
@@ -1,34 +1,25 @@
 package com.appsmith.external.helpers.restApiUtils.helpers;
 
 import com.appsmith.external.models.ActionConfiguration;
 import com.appsmith.external.models.DatasourceConfiguration;
 import com.appsmith.external.models.Property;
-import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.util.UriComponentsBuilder;
 
-import java.net.InetAddress;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLEncoder;
-import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
 
 import static org.apache.commons.collections.CollectionUtils.isEmpty;
 import static org.apache.commons.lang3.StringUtils.isNotEmpty;
 
 @NoArgsConstructor
 public class URIUtils {
-    public static final Set<String> DISALLOWED_HOSTS = Set.of(
-            "169.254.169.254",
-            "metadata.google.internal"
-    );
 
     public URI createUriWithQueryParams(ActionConfiguration actionConfiguration,
                                         DatasourceConfiguration datasourceConfiguration, String url,
                                         boolean encodeParamsToggle) throws URISyntaxException {
         String httpUrl = addHttpToUrlWhenPrefixNotPresent(url);
@@ -51,11 +42,11 @@ public class URIUtils {
 
         if (allQueryParams != null) {
             for (Property queryParam : allQueryParams) {
                 String key = queryParam.getKey();
                 if (isNotEmpty(key)) {
-                    if (encodeParamsToggle == true) {
+                    if (encodeParamsToggle) {
                         uriBuilder.queryParam(
                                 URLEncoder.encode(key, StandardCharsets.UTF_8),
                                 URLEncoder.encode((String) queryParam.getValue(), StandardCharsets.UTF_8)
                         );
                     } else {
@@ -76,11 +67,6 @@ public class URIUtils {
             return url;
         }
         return "http://" + url;
     }
 
-    public boolean isHostDisallowed(URI uri) throws UnknownHostException {
-        String host = uri.getHost();
-        return StringUtils.isEmpty(host) || DISALLOWED_HOSTS.contains(host)
-                || DISALLOWED_HOSTS.contains(InetAddress.getByName(host).getHostAddress());
-    }
 }
diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java
index 8861dd16e..f87b62fa3 100644
--- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java
+++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java
@@ -1,13 +1,33 @@
 package com.appsmith.util;
 
+import io.netty.resolver.AddressResolver;
+import io.netty.resolver.AddressResolverGroup;
+import io.netty.resolver.InetNameResolver;
+import io.netty.resolver.InetSocketAddressResolver;
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.Promise;
+import io.netty.util.internal.SocketUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.client.reactive.ReactorClientHttpConnector;
 import org.springframework.web.reactive.function.client.WebClient;
 import reactor.netty.http.client.HttpClient;
 
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
 public class WebClientUtils {
 
+    private static final Set<String> DISALLOWED_HOSTS = Set.of(
+            "169.254.169.254",
+            "metadata.google.internal"
+    );
+
     private WebClientUtils() {
     }
 
     public static WebClient create() {
         return builder()
@@ -29,17 +49,88 @@ public class WebClientUtils {
         return builder(HttpClient.create());
     }
 
     public static WebClient.Builder builder(HttpClient httpClient) {
         return WebClient.builder()
-                .clientConnector(new ReactorClientHttpConnector(applyProxyIfConfigured(httpClient)));
+                .clientConnector(new ReactorClientHttpConnector(makeSafeHttpClient(httpClient)));
     }
 
-    private static HttpClient applyProxyIfConfigured(HttpClient httpClient) {
+    private static HttpClient makeSafeHttpClient(HttpClient httpClient) {
         if (shouldUseSystemProxy()) {
             httpClient = httpClient.proxyWithSystemProperties();
         }
 
-        return httpClient;
+        return httpClient.resolver(ResolverGroup.INSTANCE);
+    }
+
+    private static class ResolverGroup extends AddressResolverGroup<InetSocketAddress> {
+        public static final ResolverGroup INSTANCE = new ResolverGroup();
+
+        @Override
+        protected AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) {
+            return new InetSocketAddressResolver(executor, new NameResolver(executor));
+        }
+    }
+
+    @Slf4j
+    private static class NameResolver extends InetNameResolver {
+
+        public NameResolver(EventExecutor executor) {
+            super(executor);
+        }
+
+        private static boolean isDisallowedAndFail(String host, Promise<?> promise) {
+            if (DISALLOWED_HOSTS.contains(host)) {
+                log.warn("Host {} is disallowed. Failing the request.", host);
+                promise.setFailure(new UnknownHostException("Host not allowed."));
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        protected void doResolve(String inetHost, Promise<InetAddress> promise) {
+            if (isDisallowedAndFail(inetHost, promise)) {
+                return;
+            }
+
+            final InetAddress address;
+            try {
+                address = SocketUtils.addressByName(inetHost);
+            } catch (UnknownHostException e) {
+                promise.setFailure(e);
+                return;
+            }
+
+            if (isDisallowedAndFail(address.getHostAddress(), promise)) {
+                return;
+            }
+
+            promise.setSuccess(address);
+        }
+
+        @Override
+        protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) {
+            if (isDisallowedAndFail(inetHost, promise)) {
+                return;
+            }
+
+            final List<InetAddress> addresses;
+            try {
+                addresses = Arrays.asList(SocketUtils.allAddressesByName(inetHost));
+            } catch (UnknownHostException e) {
+                promise.setFailure(e);
+                return;
+            }
+
+            // Even if _one_ of the addresses is disallowed, we fail the request.
+            for (InetAddress address : addresses) {
+                if (isDisallowedAndFail(address.getHostAddress(), promise)) {
+                    return;
+                }
+            }
+
+            promise.setSuccess(addresses);
+        }
     }
 
 }
diff --git a/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java b/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java
index 8cda9bd18..8453494cc 100644
--- a/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java
+++ b/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java
@@ -25,26 +25,25 @@ import org.springframework.http.HttpMethod;
 import org.springframework.web.reactive.function.client.WebClient;
 import reactor.core.publisher.Mono;
 
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import static com.appsmith.external.helpers.PluginUtils.getValueSafelyFromPropertyList;
 import static com.appsmith.external.helpers.PluginUtils.setValueSafelyInPropertyList;
 import static com.external.utils.GraphQLBodyUtils.PAGINATION_DATA_INDEX;
-import static com.external.utils.GraphQLDataTypeUtils.smartlyReplaceGraphQLQueryBodyPlaceholderWithValue;
-import static com.external.utils.GraphQLPaginationUtils.updateVariablesWithPaginationValues;
 import static com.external.utils.GraphQLBodyUtils.QUERY_VARIABLES_INDEX;
 import static com.external.utils.GraphQLBodyUtils.convertToGraphQLPOSTBodyFormat;
 import static com.external.utils.GraphQLBodyUtils.getGraphQLQueryParamsForBodyAndVariables;
 import static com.external.utils.GraphQLBodyUtils.validateBodyAndVariablesSyntax;
+import static com.external.utils.GraphQLDataTypeUtils.smartlyReplaceGraphQLQueryBodyPlaceholderWithValue;
+import static com.external.utils.GraphQLPaginationUtils.updateVariablesWithPaginationValues;
 import static java.lang.Boolean.TRUE;
 import static org.apache.commons.lang3.StringUtils.isBlank;
 
 public class GraphQLPlugin extends BasePlugin {
 
@@ -184,22 +183,10 @@ public class GraphQLPlugin extends BasePlugin {
             }
 
             ActionExecutionRequest actionExecutionRequest =
                     RequestCaptureFilter.populateRequestFields(actionConfiguration, uri, insertedParams, objectMapper);
 
-            try {
-                if (uriUtils.isHostDisallowed(uri)) {
-                    errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Host not allowed."));
-                    errorResult.setRequest(actionExecutionRequest);
-                    return Mono.just(errorResult);
-                }
-            } catch (UnknownHostException e) {
-                errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Unknown host."));
-                errorResult.setRequest(actionExecutionRequest);
-                return Mono.just(errorResult);
-            }
-
             WebClient.Builder webClientBuilder = triggerUtils.getWebClientBuilder(actionConfiguration,
                     datasourceConfiguration);
 
             String reqContentType = headerUtils.getRequestContentType(actionConfiguration, datasourceConfiguration);
 
@@ -280,11 +267,11 @@ public class GraphQLPlugin extends BasePlugin {
                     httpMethod);
             WebClient client = triggerUtils.getWebClient(webClientBuilder, apiConnection, reqContentType, objectMapper,
                     EXCHANGE_STRATEGIES, requestCaptureFilter);
 
             /* Triggering the actual REST API call */
-            Set<String> hintMessages = new HashSet<String>();
+            Set<String> hintMessages = new HashSet<>();
             return triggerUtils.triggerApiCall(client, httpMethod, uri, requestBodyObj, actionExecutionRequest,
                     objectMapper,
                     hintMessages, errorResult, requestCaptureFilter);
         }
 
diff --git a/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java
index ec1ae5b91..86f9101cc 100644
--- a/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java
+++ b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java
@@ -3,32 +3,32 @@ package com.external.plugins;
 import com.appsmith.external.dtos.ExecuteActionDTO;
 import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
 import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
 import com.appsmith.external.helpers.DataTypeStringUtils;
 import com.appsmith.external.helpers.MustacheHelper;
+import com.appsmith.external.helpers.restApiUtils.connections.APIConnection;
+import com.appsmith.external.helpers.restApiUtils.helpers.RequestCaptureFilter;
 import com.appsmith.external.models.ActionConfiguration;
 import com.appsmith.external.models.ActionExecutionRequest;
 import com.appsmith.external.models.ActionExecutionResult;
 import com.appsmith.external.models.DatasourceConfiguration;
 import com.appsmith.external.models.PaginationField;
 import com.appsmith.external.models.PaginationType;
 import com.appsmith.external.models.Property;
 import com.appsmith.external.plugins.BasePlugin;
 import com.appsmith.external.plugins.BaseRestApiPluginExecutor;
 import com.appsmith.external.services.SharedConfig;
-import com.appsmith.external.helpers.restApiUtils.connections.APIConnection;
-import com.appsmith.external.helpers.restApiUtils.helpers.RequestCaptureFilter;
 import lombok.extern.slf4j.Slf4j;
 import org.pf4j.Extension;
 import org.pf4j.PluginWrapper;
 import org.springframework.http.HttpMethod;
 import org.springframework.web.reactive.function.client.WebClient;
 import reactor.core.publisher.Mono;
+
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLDecoder;
-import java.net.UnknownHostException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -123,11 +123,11 @@ public class RestApiPlugin extends BasePlugin {
             // Initializing object for error condition
             ActionExecutionResult errorResult = new ActionExecutionResult();
             initUtils.initializeResponseWithError(errorResult);
 
             // Set of hint messages that can be returned to the user.
-            Set<String> hintMessages = new HashSet();
+            Set<String> hintMessages = new HashSet<>();
 
             // Initializing request URL
             String url = initUtils.initializeRequestUrl(actionConfiguration, datasourceConfiguration);
 
             Boolean encodeParamsToggle = headerUtils.isEncodeParamsToggleEnabled(actionConfiguration);
@@ -146,22 +146,10 @@ public class RestApiPlugin extends BasePlugin {
             }
 
             ActionExecutionRequest actionExecutionRequest =
                     RequestCaptureFilter.populateRequestFields(actionConfiguration, uri, insertedParams, objectMapper);
 
-            try {
-                if (uriUtils.isHostDisallowed(uri)) {
-                    errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Host not allowed."));
-                    errorResult.setRequest(actionExecutionRequest);
-                    return Mono.just(errorResult);
-                }
-            } catch (UnknownHostException e) {
-                errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Unknown host."));
-                errorResult.setRequest(actionExecutionRequest);
-                return Mono.just(errorResult);
-            }
-
             WebClient.Builder webClientBuilder = triggerUtils.getWebClientBuilder(actionConfiguration,
                     datasourceConfiguration);
             String reqContentType = headerUtils.getRequestContentType(actionConfiguration, datasourceConfiguration);
 
             /* Check for content type */

Vulnerable code: import java.net.InetAddress;
import java.net.UnknownHostException;
import static com.appsmith.external.helpers.restApiUtils.helpers.URIUtils.DISALLOWED_HOSTS;
                        URI redirectUri;
                            if (DISALLOWED_HOSTS.contains(redirectUri.getHost())
                                    || DISALLOWED_HOSTS.contains(InetAddress.getByName(redirectUri.getHost()).getHostAddress())) {
                                return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, "Host not allowed."));
                            }
                        } catch (URISyntaxException | UnknownHostException e) {
import lombok.AccessLevel;
import org.apache.commons.lang3.StringUtils;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Set;
    public static final Set<String> DISALLOWED_HOSTS = Set.of(
            "169.254.169.254",
            "metadata.google.internal"
    );
                    if (encodeParamsToggle == true) {
    public boolean isHostDisallowed(URI uri) throws UnknownHostException {
        String host = uri.getHost();
        return StringUtils.isEmpty(host) || DISALLOWED_HOSTS.contains(host)
                || DISALLOWED_HOSTS.contains(InetAddress.getByName(host).getHostAddress());
    }
                .clientConnector(new ReactorClientHttpConnector(applyProxyIfConfigured(httpClient)));
    private static HttpClient applyProxyIfConfigured(HttpClient httpClient) {
        return httpClient;
import java.net.UnknownHostException;
import static com.external.utils.GraphQLDataTypeUtils.smartlyReplaceGraphQLQueryBodyPlaceholderWithValue;
import static com.external.utils.GraphQLPaginationUtils.updateVariablesWithPaginationValues;
            try {
                if (uriUtils.isHostDisallowed(uri)) {
                    errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Host not allowed."));
                    errorResult.setRequest(actionExecutionRequest);
                    return Mono.just(errorResult);
                }
            } catch (UnknownHostException e) {
                errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Unknown host."));
                errorResult.setRequest(actionExecutionRequest);
                return Mono.just(errorResult);
            }

            Set<String> hintMessages = new HashSet<String>();
import com.appsmith.external.helpers.restApiUtils.connections.APIConnection;
import com.appsmith.external.helpers.restApiUtils.helpers.RequestCaptureFilter;
import java.net.UnknownHostException;
            Set<String> hintMessages = new HashSet();
            try {
                if (uriUtils.isHostDisallowed(uri)) {
                    errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Host not allowed."));
                    errorResult.setRequest(actionExecutionRequest);
                    return Mono.just(errorResult);
                }
            } catch (UnknownHostException e) {
                errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Unknown host."));
                errorResult.setRequest(actionExecutionRequest);
                return Mono.just(errorResult);
            }

Fixed code:                         final URI redirectUri;
                        } catch (URISyntaxException e) {
                    if (encodeParamsToggle) {
import io.netty.resolver.AddressResolver;
import io.netty.resolver.AddressResolverGroup;
import io.netty.resolver.InetNameResolver;
import io.netty.resolver.InetSocketAddressResolver;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.SocketUtils;
import lombok.extern.slf4j.Slf4j;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

    private static final Set<String> DISALLOWED_HOSTS = Set.of(
            "169.254.169.254",
            "metadata.google.internal"
    );

                .clientConnector(new ReactorClientHttpConnector(makeSafeHttpClient(httpClient)));
    private static HttpClient makeSafeHttpClient(HttpClient httpClient) {
        return httpClient.resolver(ResolverGroup.INSTANCE);
    }

    private static class ResolverGroup extends AddressResolverGroup<InetSocketAddress> {
        public static final ResolverGroup INSTANCE = new ResolverGroup();

        @Override
        protected AddressResolver<InetSocketAddress> newResolver(EventExecutor executor) {
            return new InetSocketAddressResolver(executor, new NameResolver(executor));
        }
    }

    @Slf4j
    private static class NameResolver extends InetNameResolver {

        public NameResolver(EventExecutor executor) {
            super(executor);
        }

        private static boolean isDisallowedAndFail(String host, Promise<?> promise) {
            if (DISALLOWED_HOSTS.contains(host)) {
                log.warn("Host {} is disallowed. Failing the request.", host);
                promise.setFailure(new UnknownHostException("Host not allowed."));
                return true;
            }
            return false;
        }

        @Override
        protected void doResolve(String inetHost, Promise<InetAddress> promise) {
            if (isDisallowedAndFail(inetHost, promise)) {
                return;
            }

            final InetAddress address;
            try {
                address = SocketUtils.addressByName(inetHost);
            } catch (UnknownHostException e) {
                promise.setFailure(e);
                return;
            }

            if (isDisallowedAndFail(address.getHostAddress(), promise)) {
                return;
            }

            promise.setSuccess(address);
        }

        @Override
        protected void doResolveAll(String inetHost, Promise<List<InetAddress>> promise) {
            if (isDisallowedAndFail(inetHost, promise)) {
                return;
            }

            final List<InetAddress> addresses;
            try {
                addresses = Arrays.asList(SocketUtils.allAddressesByName(inetHost));
            } catch (UnknownHostException e) {
                promise.setFailure(e);
                return;
            }

            // Even if _one_ of the addresses is disallowed, we fail the request.
            for (InetAddress address : addresses) {
                if (isDisallowedAndFail(address.getHostAddress(), promise)) {
                    return;
                }
            }

            promise.setSuccess(addresses);
        }
import static com.external.utils.GraphQLDataTypeUtils.smartlyReplaceGraphQLQueryBodyPlaceholderWithValue;
import static com.external.utils.GraphQLPaginationUtils.updateVariablesWithPaginationValues;
            Set<String> hintMessages = new HashSet<>();
import com.appsmith.external.helpers.restApiUtils.connections.APIConnection;
import com.appsmith.external.helpers.restApiUtils.helpers.RequestCaptureFilter;

            Set<String> hintMessages = new HashSet<>();