{"record":{"id":"463cb85826321d75","repo":"apache/dolphinscheduler","slug":"illegal-resource-path-463cb8","errorCode":"ILLEGAL_RESOURCE_PATH","errorMessage":"ILLEGAL_RESOURCE_PATH","messagePattern":"ILLEGAL_RESOURCE_PATH","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/CreateDirectoryRequestTransformer.java","lineNumber":83,"sourceCode":"    }\n\n    private String getDirectoryAbsolutePath(CreateDirectoryRequest createDirectoryRequest) {\n        String tenantCode = tenantDao.queryOptionalById(createDirectoryRequest.getLoginUser().getTenantId())\n                .orElseThrow(() -> new ServiceException(Status.CURRENT_LOGIN_USER_TENANT_NOT_EXIST))\n                .getTenantCode();\n        String userResRootPath = storageOperator.getStorageBaseDirectory(tenantCode, createDirectoryRequest.getType());\n        String parentDirectoryName = createDirectoryRequest.getParentAbsoluteDirectory();\n        String directoryName = createDirectoryRequest.getDirectoryName();\n\n        // If the parent directory is / then will transform to userResRootPath\n        // This only happens when the front-end go into the resource page first\n        // todo: we need to change the front-end logic to avoid this\n        if (parentDirectoryName.equals(\"/\")) {\n            return FileUtils.concatFilePath(userResRootPath, directoryName);\n        }\n\n        if (!StringUtils.startsWith(parentDirectoryName, userResRootPath)) {\n            throw new ServiceException(Status.ILLEGAL_RESOURCE_PATH, parentDirectoryName);\n        }\n        return FileUtils.concatFilePath(parentDirectoryName, directoryName);\n    }\n}\n","sourceCodeStart":65,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/CreateDirectoryRequestTransformer.java#L65-L88","documentation":"CreateDirectoryRequestTransformer.getDirectoryAbsolutePath throws a ServiceException with status ILLEGAL_RESOURCE_PATH when the supplied parentDirectoryName is not under the requesting user's resource root path, refusing to build a child path outside the user's allowed tree.","triggerScenarios":"Creating a directory where the parent path sent by the client does not start with the user's root (userResRootPath, i.e. '/<tenantCode>/resources'); typically only '/' (root) is special-cased and allowed.","commonSituations":"Tampered/malformed front-end requests; stale clients caching old root paths after tenant or storage-config changes; scripts calling the REST API with absolute paths outside the user's resource tree.","solutions":["Send a parent path that begins with the user's resource root (e.g. '/tenantA/resources'), or send '/' to create at the root level.","Re-fetch the directory tree from the API instead of using cached/typed paths.","Verify the logged-in user's tenant matches the tenant prefix in the parent path.","If this fires from the bundled UI, upgrade — the code notes the front-end logic needs updating to avoid it."],"exampleFix":"// before: parent outside the user's root\ncreateDirectory(parentDirectoryName = \"/otherTenant/resources\", directoryName = \"jobs\");\n// after\ncreateDirectory(parentDirectoryName = \"/myTenant/resources\", directoryName = \"jobs\");","handlingStrategy":"validation","validationCode":"String root = \"/\" + tenantCode + \"/resources\"; if (parentDirectoryName != null && !parentDirectoryName.equals(\"/\") && !parentDirectoryName.startsWith(root)) { throw new IllegalArgumentException(\"Parent outside user root: \" + parentDirectoryName); }","typeGuard":"boolean isLegalParent(String parent, String root) { return \"/\".equals(parent) || (parent != null && parent.startsWith(root)); }","tryCatchPattern":"try { createDirectory(...); } catch (ServiceException e) { if (\"ILLEGAL_RESOURCE_PATH\".equals(e.getCode())) { /* rebuild parent from user root and retry */ } else { throw e; } }","preventionTips":["Always derive parent paths from the user's resource root, never from raw user input.","Send '/' explicitly when creating a top-level directory.","Keep API clients updated so cached root paths match the server's userResRootPath."],"tags":["resource","path-validation","illegal-path","dolphinscheduler"],"backgroundTag":"path-traversal-blocked","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}