Affected Component
me.zhengjie.rest.LocalStorageController.createFile(...)
me.zhengjie.service.impl.LocalStorageServiceImpl.create(...)
me.zhengjie.utils.FileUtil.upload(...)
Description
The upload flow partially sanitizes the user-controlled filename, but the final destination path is constructed using a suffix derived from the raw MultipartFile.getOriginalFilename() value. That suffix is not sanitized before being concatenated into the final filesystem path.
As a result, a crafted filename can inject path traversal elements into the computed destination path. The destination File is then normalized with getCanonicalFile(), which may resolve the traversal and place the uploaded file outside the intended upload directory.
Affected Code Path
LocalStorageController.createFile(name, file)
→ LocalStorageServiceImpl.create(name, multipartFile)
→ FileUtil.upload(multipartFile, filePath)
→ MultipartFile.transferTo(dest)
Root Cause
In FileUtil.upload(...):
String name = getFileNameNoEx(verifyFilename(file.getOriginalFilename()));
String suffix = getExtensionName(file.getOriginalFilename());
String fileName = name + nowStr + "." + suffix;
String path = filePath + fileName;
File dest = (new File(path)).getCanonicalFile();
file.transferTo(dest);
verifyFilename() is applied only to name.
suffix is extracted from the raw filename and is not sanitized.
Security Impact
An authenticated attacker with permission to access the upload endpoint may be able to write a file outside the intended upload directory. Depending on deployment permissions and target location, this can lead to:
- arbitrary file write within the application’s writable scope
- overwrite of application-controlled files
- further compromise if the written file is executable or consumed by another component
POC
------WebKitFormBoundaryOZfP2Gqc31W0qyeS
Content-Disposition: form-data; name="file"; filename="x/../../../../evil.ai."
Content-Type: text/javascript
hello
------WebKitFormBoundaryOZfP2Gqc31W0qyeS--
The file was eventually uploaded to the C drive.

Affected Component
me.zhengjie.rest.LocalStorageController.createFile(...)
me.zhengjie.service.impl.LocalStorageServiceImpl.create(...)
me.zhengjie.utils.FileUtil.upload(...)
Description
The upload flow partially sanitizes the user-controlled filename, but the final destination path is constructed using a suffix derived from the raw MultipartFile.getOriginalFilename() value. That suffix is not sanitized before being concatenated into the final filesystem path.
As a result, a crafted filename can inject path traversal elements into the computed destination path. The destination File is then normalized with getCanonicalFile(), which may resolve the traversal and place the uploaded file outside the intended upload directory.
Affected Code Path
LocalStorageController.createFile(name, file)
→ LocalStorageServiceImpl.create(name, multipartFile)
→ FileUtil.upload(multipartFile, filePath)
→ MultipartFile.transferTo(dest)
Root Cause
verifyFilename() is applied only to name.
suffix is extracted from the raw filename and is not sanitized.
Security Impact
An authenticated attacker with permission to access the upload endpoint may be able to write a file outside the intended upload directory. Depending on deployment permissions and target location, this can lead to:
POC
The file was eventually uploaded to the C drive.