Severity: High · CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
Affected versions:v1.4.0
Summary
Creating a cluster accepts a free-text cluster name and persists it after only a uniqueness check, with no validation of path characters. The stored name is later used verbatim to build a kerberos work directory under the temp root; when a component's kerberos configuration is refreshed, that directory is recursively deleted via FileUtils.deleteDirectory. A clusterName containing ../ (or resolving above the temp root) causes the recursive delete to target an unintended directory, letting an authenticated operator delete arbitrary directories.
Vulnerability chain
| Stage |
Component |
Location |
| Source |
clusterName parameter (POST /cluster/addCluster) |
ClusterController.java:56 |
| Storage |
cluster.setClusterName(clusterName) persisted, no path validation |
ConsoleClusterService.java:72 |
| Read |
getLocalKerberosPath → tempDir + sep + clusterName + ... |
ConsoleComponentService.java:617 |
| Sink |
FileUtils.deleteDirectory(new File(kerberosPath)) |
ConsoleComponentService.java:494 |
addCluster persists the caller-supplied clusterName after only checking that the name is unique. Later, when a component's kerberos files are uploaded or refreshed, updateComponentKerberosFile computes the local kerberos path through getLocalKerberosPath, which concatenates the temp directory, the stored cluster name, the component type, and kerberos. That path is passed to FileUtils.deleteDirectory to clear the old kerberos directory before extraction. Because the cluster name is an unvalidated path component, a ../-bearing or absolute-looking name resolves the delete target outside the temp root.
Key code
Stored unvalidated — taier-data-develop/.../controller/console/ClusterController.java:55:
@PostMapping(value = "/addCluster")
public R<Long> addCluster(@RequestParam("clusterName") String clusterName) {
return R.ok(consoleClusterService.addCluster(clusterName));
}
taier-data-develop/.../service/console/ConsoleClusterService.java:67:
public Long addCluster(String clusterName) {
if (clusterMapper.getByClusterName(clusterName) != null) { ... }
Cluster cluster = new Cluster();
cluster.setClusterName(clusterName); // no path-character validation
clusterMapper.insert(cluster);
return cluster.getId();
}
Path built from the stored name — ConsoleComponentService.java:612:
public String getLocalKerberosPath(Long clusterId, Integer componentCode) {
Cluster one = clusterMapper.getOne(clusterId);
...
return env.getTempDir() + File.separator + one.getClusterName()
+ File.separator + EComponentType.getByCode(componentCode).name() + File.separator + KERBEROS;
}
Recursive delete on the resolved path — ConsoleComponentService.java:492:
String kerberosPath = this.getLocalKerberosPath(clusterId, addComponent.getComponentTypeCode());
try {
FileUtils.deleteDirectory(new File(kerberosPath)); // :494
} catch (IOException e) { ... }
Proof of Concept
Authenticated console operator. The requests only set up and trigger the delete; the target is a benign /tmp path and no destructive payload is delivered.
Step 1 — create a cluster whose name resolves above the temp root:
POST /cluster/addCluster HTTP/1.1
Host: <taier host>
Content-Type: application/x-www-form-urlencoded
Cookie: <taier session>
clusterName=../../../../../../../../tmp/x
Step 2 — refresh a component's kerberos configuration for that cluster (e.g. via /upload/component/addOrUpdateComponent or /upload/component/uploadKerberos), which calls updateComponentKerberosFile → getLocalKerberosPath → FileUtils.deleteDirectory(...) on the path derived from the stored name.
Impact
An authenticated operator with cluster/component-management access can cause taier to recursively delete directories outside its temp root. This can lead to denial of service or destruction of data reachable (and deletable) by the JVM user. Precondition: a valid authenticated session.
Remediation
Validate clusterName to identifier-safe characters and reject /, \, and .. before persisting. Derive filesystem paths from a non-user-controlled identifier (e.g. the numeric clusterId) rather than the free-text cluster name. Before deleting, canonicalize the resolved path and confirm it remains inside the temp root.
Severity: High · CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
Affected versions:v1.4.0
Summary
Creating a cluster accepts a free-text cluster name and persists it after only a uniqueness check, with no validation of path characters. The stored name is later used verbatim to build a kerberos work directory under the temp root; when a component's kerberos configuration is refreshed, that directory is recursively deleted via
FileUtils.deleteDirectory. AclusterNamecontaining../(or resolving above the temp root) causes the recursive delete to target an unintended directory, letting an authenticated operator delete arbitrary directories.Vulnerability chain
clusterNameparameter (POST /cluster/addCluster)ClusterController.java:56cluster.setClusterName(clusterName)persisted, no path validationConsoleClusterService.java:72getLocalKerberosPath→tempDir + sep + clusterName + ...ConsoleComponentService.java:617FileUtils.deleteDirectory(new File(kerberosPath))ConsoleComponentService.java:494addClusterpersists the caller-suppliedclusterNameafter only checking that the name is unique. Later, when a component's kerberos files are uploaded or refreshed,updateComponentKerberosFilecomputes the local kerberos path throughgetLocalKerberosPath, which concatenates the temp directory, the stored cluster name, the component type, andkerberos. That path is passed toFileUtils.deleteDirectoryto clear the old kerberos directory before extraction. Because the cluster name is an unvalidated path component, a../-bearing or absolute-looking name resolves the delete target outside the temp root.Key code
Stored unvalidated —
taier-data-develop/.../controller/console/ClusterController.java:55:taier-data-develop/.../service/console/ConsoleClusterService.java:67:Path built from the stored name —
ConsoleComponentService.java:612:Recursive delete on the resolved path —
ConsoleComponentService.java:492:Proof of Concept
Authenticated console operator. The requests only set up and trigger the delete; the target is a benign
/tmppath and no destructive payload is delivered.Step 1 — create a cluster whose name resolves above the temp root:
Step 2 — refresh a component's kerberos configuration for that cluster (e.g. via
/upload/component/addOrUpdateComponentor/upload/component/uploadKerberos), which callsupdateComponentKerberosFile→getLocalKerberosPath→FileUtils.deleteDirectory(...)on the path derived from the stored name.Impact
An authenticated operator with cluster/component-management access can cause taier to recursively delete directories outside its temp root. This can lead to denial of service or destruction of data reachable (and deletable) by the JVM user. Precondition: a valid authenticated session.
Remediation
Validate
clusterNameto identifier-safe characters and reject/,\, and..before persisting. Derive filesystem paths from a non-user-controlled identifier (e.g. the numericclusterId) rather than the free-text cluster name. Before deleting, canonicalize the resolved path and confirm it remains inside the temp root.