fix: 5 个安全/正确性问题

1. (High) 无 DB 时审批绕过 — approval_manager 始终创建,
   无 DB 时用纯内存模式,不再绕过审批
2. (High) 多用户串上下文 — user_id 改存 ChatSession,
   spawn 前写入,executor 从 session 读(而非共享 Arc)
3. (Medium) 技能超时未杀子进程 — cmd.kill_on_drop(true)
4. (Medium) provider 配置不生效 — 模型选择跟随 LLM_PROVIDER
   环境变量(deepseek/lmstudio 各自取对应模型名)
5. (Low) manage_memos 改为 High 风险(add/delete 有副作用)
This commit is contained in:
2026-06-02 10:56:44 +08:00
parent 5daaba686b
commit 5602b08faf
5 changed files with 21 additions and 20 deletions
+15 -17
View File
@@ -220,10 +220,9 @@ async fn cmd_listen(
Some(Arc::new(skill_registry))
};
// 审批管理器
let approval_manager = database
.as_ref()
.map(|db| Arc::new(ApprovalManager::new(Some(Arc::new(db.pool().clone())))));
let approval_manager = Arc::new(ApprovalManager::new(
database.as_ref().map(|db| Arc::new(db.pool().clone()))
));
// 共享的当前用户 ID(用于审批消息)
let current_user_id = Arc::new(tokio::sync::Mutex::new(String::new()));
@@ -231,7 +230,12 @@ async fn cmd_listen(
let conversation = if enable_llm {
let sys_prompt = std::env::var("WEIXIN_LLM_SYSTEM_PROMPT")
.unwrap_or_else(|_| DEFAULT_SYSTEM_PROMPT.to_string());
let model = config.llm.deepseek.model.clone();
let provider = std::env::var("LLM_PROVIDER").unwrap_or_else(|_| "deepseek".to_string());
let model = if provider == "lmstudio" {
config.llm.lmstudio.model.clone()
} else {
config.llm.deepseek.model.clone()
};
let mut cfg = ConversationConfig {
system_prompt: sys_prompt,
@@ -360,7 +364,7 @@ async fn cmd_listen(
let args = args_json.to_string();
Box::pin(async move {
let user_id = current_user.lock().await.clone();
let user_id = session.lock().await.current_user_id.clone();
match n.as_str() {
"read_memories" => return Ok(memory_store.read().await),
"write_memory" => {
@@ -379,7 +383,7 @@ async fn cmd_listen(
if let Some(name) = cap_name {
if let Some(ref reg) = reg {
let mut ctx = ExecutionContext::new(&user_id);
if let Some(a) = approval { ctx = ctx.with_approval(a); }
ctx = ctx.with_approval(approval.clone());
ctx = ctx.with_wechat(send);
let result = reg.execute(&name, cap_params, &ctx).await;
return Ok(result.output);
@@ -394,9 +398,7 @@ async fn cmd_listen(
let params: serde_json::Value =
serde_json::from_str(&args).unwrap_or(serde_json::json!({}));
let mut ctx = ExecutionContext::new(&user_id);
if let Some(a) = approval {
ctx = ctx.with_approval(a);
}
ctx = ctx.with_approval(approval.clone());
ctx = ctx.with_wechat(send);
let result = reg.execute(&n, params, &ctx).await;
Ok(result.output)
@@ -451,7 +453,7 @@ async fn cmd_listen(
file_state.save_runtime(&client.get_updates_buf().await);
info!("已退出");
}
_ = listen_loop(&client, enable_llm, echo, &account_id, database, file_state, conversation, approval_manager, listen_user_id) => {}
_ = listen_loop(&client, enable_llm, echo, &account_id, database, file_state, conversation, &approval_manager, listen_user_id) => {}
}
}
@@ -463,7 +465,7 @@ async fn listen_loop(
database: &Option<Arc<Database>>,
file_state: &state::StateManager,
conversation: Option<Arc<Conversation>>,
approval_manager: Option<Arc<ApprovalManager>>,
approval_manager: &ApprovalManager,
current_user_id: Arc<tokio::sync::Mutex<String>>,
) {
loop {
@@ -526,11 +528,7 @@ async fn listen_loop(
}
// 审批回复检查
let is_approval_reply = if let Some(mgr) = &approval_manager {
mgr.handle_reply(from, text).await.is_some()
} else {
false
};
let is_approval_reply = approval_manager.handle_reply(from, text).await.is_some();
if is_approval_reply {
info!("消息匹配审批确认码,不传给 LLM");