apache/shenyu · warning · ShenyuException
is not allowed.
Error message
is not allowed.
What it means
SandboxServiceImpl.requestProxyGateway() validates that the host:port of the requested proxy URL is in the permit list (getPermitHostPorts, derived from admin config). If not, it logs 'Unsecure access' and throws ShenyuException(hostPort + " is not allowed.") to block SSRF-style requests to non-whitelisted gateway hosts.
Solutions
- Add the exact host:port of the target gateway to the sandbox permit host ports configuration in shenyu-admin (the value produced by getHostPort must match exactly, including port).
- Print/compare getHostPort(requestUrl) with configured permit entries to catch formatting mismatches (default port, scheme, trailing slash).
- Use the configured gateway address in the sandbox request URL instead of localhost/127.0.0.1 or an internal hostname.
- Catch ShenyuException and show a clear message that the host must be allowlisted for the sandbox.
Example fix
// before (admin config) shenyu.sandbox.permit-host-ports=gateway.prod:9195 // request: http://localhost:9195/... // after (admin config) shenyu.sandbox.permit-host-ports=gateway.prod:9195,localhost:9195 // request now matches an allowlisted host:port
Defensive patterns
Strategy: validation
Validate before calling
String hostPort = requestUrl == null ? null : UriComponentsBuilder.fromHttpUrl(requestUrl).build().getHost()
+ (UriComponentsBuilder.fromHttpUrl(requestUrl).build().getPort() != -1 ? ":" + UriComponentsBuilder.fromHttpUrl(requestUrl).build().getPort() : "");
if (!permitHostPorts.contains(hostPort)) {
throw new IllegalArgumentException("host:port not allowlisted for sandbox: " + hostPort);
} Try / catch
try {
sandboxService.requestProxyGateway(/* ... */);
} catch (ShenyuException e) {
if (e.getMessage() != null && e.getMessage().endsWith("is not allowed.")) { /* surface allowlist guidance to user */ } else { throw e; }
} Prevention
- Keep the sandbox permit host-ports config in sync with actual gateway addresses, including ports.
- Use the exact allowlisted host:port string in request URLs (watch default ports and localhost vs hostname).
- Update the allowlist whenever gateways move hosts or ports.
- Treat this as a security control: never bypass it; request the host be added instead.
When it happens
Trigger: Calling the sandbox proxy API with a requestUrl whose host:port is not in the configured permitted host ports — e.g. proxying to http://localhost:9195 when only http://gateway:9195 is whitelisted, or an internal/dev URL not yet added to the sandbox allowlist.
Common situations: shenyu.sandbox permit host config missing or stale after the gateway moved hosts/ports; testing against a local gateway while admin config points at production hostnames; trailing default ports (localhost:9195 vs localhost) causing host-port string mismatch; SSRF protection rejecting internal addresses.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- websocket sync token is not configured
- websocket sync token is invalid
- URL cannot be empty
- Invalid URL format
- Only HTTP and HTTPS protocols are allowed
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/436c16427de2b325.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SandboxServiceImpl.java:90
public SandboxServiceImpl(final AppAuthService appAuthService, final ShenyuDictService shenyuDictService) {
this.appAuthService = appAuthService;
this.shenyuDictService = shenyuDictService;
}
@Override
public void requestProxyGateway(final ProxyGatewayDTO proxyGatewayDTO, final HttpServletRequest request, final HttpServletResponse response) throws IOException {
// Public request headers.
Map<String, String> header = this.buildReqHeaders(proxyGatewayDTO);
String appKey = proxyGatewayDTO.getAppKey();
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(proxyGatewayDTO.getRequestUrl()).build();
String proxyHostPort = getHostPort(proxyGatewayDTO.getRequestUrl());
Set<String> permitHostPorts = getPermitHostPorts();
if (!permitHostPorts.contains(proxyHostPort)) {
LOG.error("Unsecure access, details: {}", proxyGatewayDTO.getRequestUrl());
throw new ShenyuException(proxyHostPort + " is not allowed.");
}
String sign = null;
String timestamp = String.valueOf(Instant.now().toEpochMilli());
if (StringUtils.isNotEmpty(appKey)) {
String secureKey = getSecureKey(appKey);
Assert.notBlack(secureKey, Constants.SIGN_APP_KEY_IS_NOT_EXIST);
String signContent = ShenyuSignatureUtils.getSignContent(secureKey, timestamp, uriComponents.getPath());
sign = ShenyuSignatureUtils.generateSign(signContent);
header.put("timestamp", timestamp);
header.put("appKey", appKey);
header.put("sign", sign);
header.put("version", ShenyuSignatureUtils.VERSION);
}
// Public request parameters.
Map<String, Object> reqParams = this.buildReqBizParams(proxyGatewayDTO);
List<HttpUtils.UploadFile> files = this.uploadFiles(request);View on GitHub (pinned to 567142e072)