收紧产物文件名对远端扩展名的取值

- filename 直接取远端 URL 末段扩展名,path_segments 已百分号解码,%2F / %5C 会拼出跨目录路径
- 扩展名只接受长度不超过 10 的 ASCII 字母数字,其余一律退回 glb
This commit is contained in:
2026-09-21 15:13:15 +08:00
parent 03d5cde838
commit 6724f8b707
@@ -13,6 +13,9 @@ use crate::{
text_to_model::result::TripoTextToModelResult,
};
/// 从远端地址推导出的扩展名上限;超出即按不可信处理,退回默认扩展名。
const MAX_ARTIFACT_FILE_EXTENSION_LEN: usize = 10;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TripoTaskHandle {
pub task_id: String,
@@ -167,6 +170,9 @@ impl TripoDownloadedArtifact {
}
}
/// 产物落盘用的文件名。远端地址不可信,扩展名只接受短的字母数字 token:
/// `Url::path_segments` 已做百分号解码,`%2F` / `%5C` 这类编码分隔符会直接
/// 进到扩展名里,不过滤就会拼出跨目录的路径。
pub fn filename(&self, name: &str) -> String {
let extension = self
.url
@@ -175,7 +181,11 @@ impl TripoDownloadedArtifact {
.and_then(|segments| segments.last())
.and_then(|segment| segment.rsplit_once('.'))
.map(|(_, extension)| extension)
.filter(|extension| !extension.is_empty())
.filter(|extension| {
!extension.is_empty()
&& extension.len() <= MAX_ARTIFACT_FILE_EXTENSION_LEN
&& extension.bytes().all(|byte| byte.is_ascii_alphanumeric())
})
.unwrap_or("glb");
format!("{name}.{extension}")
}