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

  1. 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).
  2. Print/compare getHostPort(requestUrl) with configured permit entries to catch formatting mismatches (default port, scheme, trailing slash).
  3. Use the configured gateway address in the sandbox request URL instead of localhost/127.0.0.1 or an internal hostname.
  4. 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

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


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)