{"record":{"id":"436c16427de2b325","repo":"apache/shenyu","slug":"is-not-allowed","errorCode":null,"errorMessage":" is not allowed.","messagePattern":" is not allowed\\.","errorType":"exception","errorClass":"ShenyuException","httpStatus":null,"severity":"warning","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SandboxServiceImpl.java","lineNumber":90,"sourceCode":"\n    public SandboxServiceImpl(final AppAuthService appAuthService, final ShenyuDictService shenyuDictService) {\n        this.appAuthService = appAuthService;\n        this.shenyuDictService = shenyuDictService;\n    }\n\n    @Override\n    public void requestProxyGateway(final ProxyGatewayDTO proxyGatewayDTO, final HttpServletRequest request, final HttpServletResponse response) throws IOException {\n        // Public request headers.\n        Map<String, String> header = this.buildReqHeaders(proxyGatewayDTO);\n\n        String appKey = proxyGatewayDTO.getAppKey();\n        UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(proxyGatewayDTO.getRequestUrl()).build();\n        String proxyHostPort = getHostPort(proxyGatewayDTO.getRequestUrl());\n\n        Set<String> permitHostPorts = getPermitHostPorts();\n        if (!permitHostPorts.contains(proxyHostPort)) {\n            LOG.error(\"Unsecure access, details: {}\", proxyGatewayDTO.getRequestUrl());\n            throw new ShenyuException(proxyHostPort + \" is not allowed.\");\n        }\n\n        String sign = null;\n        String timestamp = String.valueOf(Instant.now().toEpochMilli());\n        if (StringUtils.isNotEmpty(appKey)) {\n            String secureKey = getSecureKey(appKey);\n            Assert.notBlack(secureKey, Constants.SIGN_APP_KEY_IS_NOT_EXIST);\n            String signContent = ShenyuSignatureUtils.getSignContent(secureKey, timestamp, uriComponents.getPath());\n            sign = ShenyuSignatureUtils.generateSign(signContent);\n            header.put(\"timestamp\", timestamp);\n            header.put(\"appKey\", appKey);\n            header.put(\"sign\", sign);\n            header.put(\"version\", ShenyuSignatureUtils.VERSION);\n        }\n\n        // Public request parameters.\n        Map<String, Object> reqParams = this.buildReqBizParams(proxyGatewayDTO);\n        List<HttpUtils.UploadFile> files = this.uploadFiles(request);","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SandboxServiceImpl.java#L72-L108","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (admin config)\nshenyu.sandbox.permit-host-ports=gateway.prod:9195\n// request: http://localhost:9195/...\n\n// after (admin config)\nshenyu.sandbox.permit-host-ports=gateway.prod:9195,localhost:9195\n// request now matches an allowlisted host:port","handlingStrategy":"validation","validationCode":"String hostPort = requestUrl == null ? null : UriComponentsBuilder.fromHttpUrl(requestUrl).build().getHost()\n    + (UriComponentsBuilder.fromHttpUrl(requestUrl).build().getPort() != -1 ? \":\" + UriComponentsBuilder.fromHttpUrl(requestUrl).build().getPort() : \"\");\nif (!permitHostPorts.contains(hostPort)) {\n    throw new IllegalArgumentException(\"host:port not allowlisted for sandbox: \" + hostPort);\n}","typeGuard":null,"tryCatchPattern":"try {\n    sandboxService.requestProxyGateway(/* ... */);\n} catch (ShenyuException e) {\n    if (e.getMessage() != null && e.getMessage().endsWith(\"is not allowed.\")) { /* surface allowlist guidance to user */ } else { throw e; }\n}","preventionTips":["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."],"tags":["ssrf-protection","allowlist","security","sandbox"],"backgroundTag":"invalid-url","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}