Skip to content

Commit ed42815

Browse files
committed
🔒 Uncontrolled data used in path expression #98
1 parent e7bbbaf commit ed42815

1 file changed

Lines changed: 56 additions & 5 deletions

File tree

backend/services/data-management-service/src/main/java/com/datamate/datamanagement/application/DatasetFileApplicationService.java

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ public void deleteDatasetFile(String datasetId, String fileId, String prefix) {
240240
// 删除文件时,上传到数据集中的文件会同时删除数据库中的记录和文件系统中的文件,归集过来的文件仅删除数据库中的记录
241241
if (file.getFilePath().startsWith(dataset.getPath())) {
242242
try {
243-
Path filePath = Paths.get(file.getFilePath());
243+
Path filePath = validateAndResolvePath(file.getFilePath(), dataset.getPath());
244244
Files.deleteIfExists(filePath);
245245
} catch (IOException ex) {
246246
throw BusinessException.of(SystemErrorCode.FILE_SYSTEM_ERROR);
@@ -293,8 +293,10 @@ public void batchDeleteFiles(String datasetId, BatchDeleteFilesRequest request)
293293
// 上传到数据集中的文件会同时删除数据库中的记录和文件系统中的文件,归集过来的文件仅删除数据库中的记录
294294
if (file.getFilePath().startsWith(dataset.getPath())) {
295295
try {
296-
Path filePath = Paths.get(file.getFilePath());
296+
Path filePath = validateAndResolvePath(file.getFilePath(), dataset.getPath());
297297
Files.deleteIfExists(filePath);
298+
} catch (IllegalArgumentException ex) {
299+
log.warn("Invalid file path detected, skipping deletion: {}", file.getFilePath());
298300
} catch (IOException ex) {
299301
log.error("Failed to delete file from filesystem: {}", file.getFilePath(), ex);
300302
}
@@ -313,7 +315,14 @@ public void batchDeleteFiles(String datasetId, BatchDeleteFilesRequest request)
313315
@Transactional(readOnly = true)
314316
public Resource downloadFile(DatasetFile file) {
315317
try {
316-
Path filePath = Paths.get(file.getFilePath()).normalize();
318+
// 获取对应的数据集以验证路径安全性
319+
Dataset dataset = datasetRepository.getById(file.getDatasetId());
320+
if (dataset == null) {
321+
throw new RuntimeException("Dataset not found for file: " + file.getFileName());
322+
}
323+
324+
// 验证路径安全性,防止路径遍历攻击
325+
Path filePath = validateAndResolvePath(file.getFilePath(), dataset.getPath());
317326
log.info("start download file {}", file.getFilePath());
318327
Resource resource = new UrlResource(filePath.toUri());
319328
if (resource.exists()) {
@@ -931,8 +940,24 @@ private void addFile(String sourPath, String targetPath, boolean softAdd) {
931940
if (StringUtils.isBlank(sourPath) || StringUtils.isBlank(targetPath)) {
932941
return;
933942
}
934-
Path source = Paths.get(sourPath).normalize();
935-
Path target = Paths.get(targetPath).normalize();
943+
944+
// 规范化并验证源文件路径
945+
Path source;
946+
try {
947+
source = Paths.get(sourPath).normalize();
948+
} catch (Exception e) {
949+
log.warn("Invalid source file path: {}", sourPath);
950+
throw BusinessException.of(SystemErrorCode.FILE_SYSTEM_ERROR);
951+
}
952+
953+
// 规范化并验证目标文件路径
954+
Path target;
955+
try {
956+
target = Paths.get(targetPath).normalize();
957+
} catch (Exception e) {
958+
log.warn("Invalid target file path: {}", targetPath);
959+
throw BusinessException.of(SystemErrorCode.FILE_SYSTEM_ERROR);
960+
}
936961

937962
// 检查源文件是否存在且为普通文件
938963
if (!Files.exists(source) || !Files.isRegularFile(source)) {
@@ -990,4 +1015,30 @@ private static DatasetFile getDatasetFileForAdd(AddFilesRequest req, AddFilesReq
9901015
.metadata(objectMapper.writeValueAsString(file.getMetadata()))
9911016
.build();
9921017
}
1018+
1019+
/**
1020+
* 安全地验证并获取文件路径,防止路径遍历攻击
1021+
*
1022+
* @param filePath 用户提供的文件路径
1023+
* @param basePath 允许的基础路径(数据集路径)
1024+
* @return 规范化后的绝对路径
1025+
* @throws IllegalArgumentException 如果路径不在基础路径内
1026+
*/
1027+
private Path validateAndResolvePath(String filePath, String basePath) {
1028+
if (StringUtils.isEmpty(filePath)) {
1029+
throw new IllegalArgumentException("File path cannot be empty");
1030+
}
1031+
1032+
Path normalizedPath = Paths.get(filePath).normalize();
1033+
Path normalizedBasePath = Paths.get(basePath).normalize();
1034+
1035+
// 验证规范化后的路径是否在基础路径内
1036+
if (!normalizedPath.startsWith(normalizedBasePath)) {
1037+
throw new IllegalArgumentException(
1038+
"File path is outside the allowed directory: " + filePath
1039+
);
1040+
}
1041+
1042+
return normalizedPath;
1043+
}
9931044
}

0 commit comments

Comments
 (0)