{"record":{"id":"f52910c8523f4606","repo":"apache/dolphinscheduler","slug":"illegal-resource-path","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/AbstractResourceTransformer.java","lineNumber":52,"sourceCode":"\n    protected TenantDao tenantDao;\n\n    protected StorageOperator storageOperator;\n\n    protected String getParentDirectoryAbsolutePath(User loginUser, String parentAbsoluteDirectory, ResourceType type) {\n        String tenantCode = tenantDao.queryOptionalById(loginUser.getTenantId())\n                .orElseThrow(() -> new ServiceException(Status.CURRENT_LOGIN_USER_TENANT_NOT_EXIST))\n                .getTenantCode();\n        String userResRootPath = storageOperator.getStorageBaseDirectory(tenantCode, type);\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 (parentAbsoluteDirectory.equals(\"/\")) {\n            return userResRootPath;\n        }\n\n        if (!StringUtils.startsWith(parentAbsoluteDirectory, userResRootPath)) {\n            throw new ServiceException(Status.ILLEGAL_RESOURCE_PATH, parentAbsoluteDirectory);\n        }\n        return parentAbsoluteDirectory;\n    }\n}\n","sourceCodeStart":34,"sourceCodeEnd":57,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/AbstractResourceTransformer.java#L34-L57","documentation":"AbstractResourceTransformer.getParentDirectoryAbsolutePath verifies that the parent directory supplied by the client is inside the user's resource root path (/username/resources style). If parentAbsoluteDirectory does not start with the user's root, it throws ServiceException(ILLEGAL_RESOURCE_PATH) to block resource operations that escape the user's own directory tree.","triggerScenarios":"Calling resource move/copy/rename/create-directory APIs with a parentDir parameter that points outside the logged-in user's resource root (e.g. a path rooted at another tenant's directory or an absolute path like /etc).","commonSituations":"Frontend caches stale paths belonging to a previous logged-in user; manual API calls hardcoding a shared/global base directory; version changes where the storage root layout changed (the source notes the front-end logic still needs fixing).","solutions":["Pass a parentDir that begins with the current user's resource root path (visible in the resource center UI breadcrumb).","Clear the frontend state / re-login so the UI sends paths belonging to the current user.","If integrating programmatically, compute parentDir via StorageOperator.getStorageBaseDirectory + user root rather than hardcoding."],"exampleFix":"// before\nparentDir = \"/otheruser/resources\";\n// after\nparentDir = \"/alice/resources\";  // starts with current user's root path","handlingStrategy":"validation","validationCode":"// client-side pre-check\nif (!parentDir.startsWith(\"/\" + currentUser.getUserName() + \"/resources\")) {\n    throw new IllegalArgumentException(\"parentDir must be inside the user's resource root\");\n}","typeGuard":"function isWithinUserRoot(path, userRoot) {\n  return typeof path === 'string' && path.startsWith(userRoot.replace(/\\/$/, '') + '/');\n}","tryCatchPattern":"try {\n    // move/copy/rename resource\n} catch (ServiceException e) {\n    if (e.getCode() == Status.ILLEGAL_RESOURCE_PATH.getCode()) {\n        // recompute parentDir from the resource-center listing API\n    } else throw e;\n}","preventionTips":["Always derive parentDir from the resource listing/breadcrumb API of the currently logged-in user","Re-fetch paths after user or tenant switching to avoid stale paths","Never hardcode absolute storage paths in integration scripts"],"tags":["resource","path-validation","security"],"backgroundTag":"invalid-argument-value","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"}