kestra-io/kestra · error · IllegalArgumentException
The URI {} is in the configured denied list (kestra.tasks.ht
Error message
The URI {} is in the configured denied list (kestra.tasks.http.denied-list). What it means
Thrown by the Kestra HTTP client when a denied-list is configured (kestra.tasks.http.denied-list) and the request URI starts with a denied prefix. validateUri runs after the allow-list check; if deniedList.stream().anyMatch(requestUri::startsWith), it throws IllegalArgumentException naming the URI. This blocks requests to forbidden hosts (SSRF / internal-network protection).
Source
Thrown at core/src/main/java/io/kestra/core/http/client/HttpClient.java:564
}
}
@SuppressWarnings("unchecked")
private void validateUri(URI uri) {
String requestUri = uri.toString();
List<String> allowedList = (List<String>) ((DefaultRunContext) runContext).getTaskProperty("kestra.tasks.http.allowed-list", List.class).orElse(Collections.emptyList());
List<String> deniedList = (List<String>) ((DefaultRunContext) runContext).getTaskProperty("kestra.tasks.http.denied-list", List.class).orElse(Collections.emptyList());
// first check that if there is an allow list, it matches one
if (!allowedList.isEmpty()) {
if (allowedList.stream().noneMatch(requestUri::startsWith)) {
throw new IllegalArgumentException("The URI " + requestUri + " is not in the configured allowed list (kestra.tasks.http.allowed-list).");
}
}
// then check that there are no exclusion for it
if (deniedList.stream().anyMatch(requestUri::startsWith)) {
throw new IllegalArgumentException("The URI " + requestUri + " is in the configured denied list (kestra.tasks.http.denied-list).");
}
}
@SuppressWarnings("unchecked")
private <T> T bodyHandler(Class<?> cls, HttpEntity entity) throws IOException, ParseException {
if (entity == null) {
return null;
} else if (String.class.isAssignableFrom(cls)) {
return (T) EntityUtils.toString(entity);
} else if (Byte[].class.isAssignableFrom(cls)) {
return (T) ArrayUtils.toObject(EntityUtils.toByteArray(entity));
} else if (MediaType.APPLICATION_YAML.equals(entity.getContentType()) || "application/yaml".equals(entity.getContentType())) {
return (T) JacksonMapper.ofYaml().readValue(entity.getContent(), cls);
} else {
return (T) JacksonMapper.ofJson(false).readValue(entity.getContent(), cls);
}
}
View on GitHub (pinned to 823fada927)
Solutions
- Retarget the task to a host not on the denied-list.
- If the denial is too broad, narrow the denied prefix or remove the offending entry (with security approval).
- Constrain dynamic URI expressions so they cannot resolve to blocked hosts.
- Prefer the allow-list model for stricter control instead of maintaining a deny-list.
Example fix
# before task uri: "http://169.254.169.254/latest/meta-data" # denied # after task uri: "https://api.example.com/metadata" # allowed
Defensive patterns
Strategy: validation
Validate before calling
List<String> denied = getTaskProperty('kestra.tasks.http.denied-list', List.class).orElse(List.of());
if (denied.stream().anyMatch(uri.toString()::startsWith)) {
throw new IllegalStateException('URI is denied: ' + uri);
} Try / catch
try {
validateUri(uri);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains('denied list')) {
log.warn('Denied-list blocked {}', uri);
}
throw e;
} Prevention
- Keep the denied-list covering internal/link-local ranges.
- Constrain dynamic URIs away from blocked hosts.
- Prefer allow-listing for stricter control where feasible.
When it happens
Trigger: Task property kestra.tasks.http.denied-list is configured (possibly empty); request URI starts with one of the denied prefixes; the anyMatch branch throws IllegalArgumentException.
Common situations: The denied-list covers internal ranges (e.g. http://localhost, http://169.254.169.254) and the task targets one, a dynamic URI resolved to a blocked host, or the denied-list was broadened and now catches a legitimate target.
Related errors
- The URI {} is not in the configured allowed list (kestra.tas
- Digest authentication requires both `username` and `password
- Digest authentication requires an absolute URI with a host.
- Both username and password must be provided if either is pre
- The file:// protocol has been disabled inside the Kestra con
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/4700a2f109a179be.
Report an issue: GitHub.