修复: DeepSeek 400 全量扫描 + 队列 per-conv 隔离
- openai_compat: 扫描所有 assistant 消息剥离 orphan tool_calls(原仅查末条) - queue 加 conversationId 字段,按会话精准 drain - regenerate/editMessage 只清本会话排队消息 - newConversation 保留旧会话排队消息 - AiError 只清出错会话的队列项
This commit is contained in:
@@ -165,8 +165,22 @@ pub fn check_path_authorization(
|
||||
raw_path: &str,
|
||||
allowed: &AllowedDirs,
|
||||
) -> PathAuthDecision {
|
||||
// Phase C: 黑名单优先独立判定(is_authorized 内也判,此处先判便于 NeedsAuthorization
|
||||
// 不误把黑名单路径推到弹窗 — 黑名单路径直接硬拒不让用户"授权")。
|
||||
//
|
||||
// BUG-2026-07-07: 黑名单检查必须在路径规范化(is_absolute / root.join)之前对**原始路径**
|
||||
// 也判一次。原因:Windows 上 "/home/user/.ssh/config" 这类 Unix 风格路径 is_absolute() 返 false
|
||||
// (Windows 绝对路径需盘符或 UNC),会被当相对路径走 first_persistent_dir 分支;若 persistent 为空,
|
||||
// 旧逻辑直接 return NeedsAuthorization,**跳过黑名单检查** → .ssh/.aws 等敏感路径在 Windows 上绕过黑名单。
|
||||
// 修复:先用原始路径判黑名单(segment 匹配,任意路径段命中 .ssh 即拒,与路径形态无关),命中直接 Denied。
|
||||
let raw_resolved = Path::new(raw_path);
|
||||
if is_in_system_blacklist(raw_resolved) {
|
||||
return PathAuthDecision::Denied {
|
||||
reason: format!("路径命中系统敏感目录黑名单: {}", raw_path),
|
||||
};
|
||||
}
|
||||
// 规范化:绝对路径原样,相对路径锚定首个持久授权目录(与 resolve_workspace_path_impl 一致)
|
||||
let resolved = if Path::new(raw_path).is_absolute() {
|
||||
let resolved = if raw_resolved.is_absolute() {
|
||||
PathBuf::from(raw_path)
|
||||
} else if let Some(root) = allowed.first_persistent_dir() {
|
||||
root.join(raw_path)
|
||||
@@ -176,8 +190,7 @@ pub fn check_path_authorization(
|
||||
dir: PathBuf::from("."),
|
||||
};
|
||||
};
|
||||
// Phase C: 黑名单优先独立判定(is_authorized 内也判,此处先判便于 NeedsAuthorization
|
||||
// 不误把黑名单路径推到弹窗 — 黑名单路径直接硬拒不让用户"授权")。
|
||||
// 规范化后再判一次黑名单(锚定后路径形态可能变化,双保险)
|
||||
if is_in_system_blacklist(&resolved) {
|
||||
return PathAuthDecision::Denied {
|
||||
reason: format!("路径命中系统敏感目录黑名单: {}", raw_path),
|
||||
@@ -430,6 +443,38 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// BUG-2026-07-07: Windows 上 Unix 风格 .ssh 路径必须被黑名单拒(不能绕过)。
|
||||
///
|
||||
/// 背景:Windows 上 `/home/user/.ssh/config` 的 is_absolute() 返 false(无盘符),
|
||||
/// 旧逻辑在 persistent 为空时直接返 NeedsAuthorization,**跳过黑名单检查**,
|
||||
/// 致 .ssh/.aws 等敏感路径在 Windows 上绕过黑名单。修复后原始路径也判黑名单。
|
||||
/// 此测试锁死该修复:空 persistent + Unix 风格 .ssh 路径 → 必 Denied。
|
||||
#[test]
|
||||
fn test_check_path_blacklist_unix_style_ssh_on_windows() {
|
||||
let allowed = AllowedDirs::default_with_root();
|
||||
match check_path_authorization("/home/user/.ssh/config", &allowed) {
|
||||
PathAuthDecision::Denied { .. } => {}
|
||||
other => panic!("Unix 风格 .ssh 路径应 Denied(黑名单), got {:?}", other),
|
||||
}
|
||||
// 同理 .aws / .gnupg
|
||||
match check_path_authorization("/home/user/.aws/credentials", &allowed) {
|
||||
PathAuthDecision::Denied { .. } => {}
|
||||
other => panic!("Unix 风格 .aws 路径应 Denied(黑名单), got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
/// 回归:合法相对路径(非黑名单)在空 persistent 下仍应返 NeedsAuthorization(引导授权)。
|
||||
/// 修复黑名单提前后,需确认非黑名单相对路径行为不变。
|
||||
#[test]
|
||||
fn test_check_path_non_blacklist_relative_still_needs_auth() {
|
||||
let allowed = AllowedDirs::default_with_root();
|
||||
match check_path_authorization("some/regular/path", &allowed) {
|
||||
PathAuthDecision::NeedsAuthorization { .. } => {}
|
||||
other => panic!("非黑名单相对路径 + 空 persistent 应 NeedsAuthorization, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// F-260620: strip_verbatim 比对侧收口 + 黑名单增强测试
|
||||
// 三方审查(安全/UX/跨端)交叉印证:strip_verbatim 仅写入侧调用,比对侧遗漏致误弹窗。
|
||||
|
||||
Reference in New Issue
Block a user