fix(industry): 审计修复 — 4 CRITICAL + 5 HIGH 全部解决
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
C1: SaaS industry/service.rs SQL 注入风险 → 参数化查询 ($N 绑定) C2: INDUSTRY_CONFIGS 死链 → Kernel 共享 Arc 接通 ButlerRouter C3: IndustryListItem 缺 keywords_count → SQL 查询 + 类型补全 C4: set_account_industries 非事务性 → batch 验证 + 事务 DELETE+INSERT H8: Accounts.tsx mutate 竞态 → mutateAsync 顺序等待 H9: XML 注入未转义 → xml_escape() 辅助函数 H10: update_industry 覆盖 source → 保留原始值 H11: 面包屑缺少 /industries → 添加行业配置映射
This commit is contained in:
@@ -193,6 +193,22 @@ impl ButlerRouterMiddleware {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a butler router with a custom semantic routing backend AND
|
||||
/// a shared industry keywords Arc.
|
||||
///
|
||||
/// The shared Arc allows the Tauri command layer to update industry keywords
|
||||
/// through the Kernel's `industry_keywords()` field, which the middleware
|
||||
/// reads automatically — no chain rebuild needed.
|
||||
pub fn with_router_and_shared_keywords(
|
||||
router: Box<dyn ButlerRouterBackend>,
|
||||
shared_keywords: Arc<RwLock<Vec<IndustryKeywordConfig>>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
_router: Some(router),
|
||||
industry_keywords: shared_keywords,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update dynamic industry keyword configs (called from Tauri command or SaaS sync).
|
||||
pub async fn update_industry_keywords(&self, configs: Vec<IndustryKeywordConfig>) {
|
||||
let mut guard = self.industry_keywords.write().await;
|
||||
@@ -210,7 +226,7 @@ impl ButlerRouterMiddleware {
|
||||
if let Some(ref skill_id) = hint.skill_id {
|
||||
return format!(
|
||||
"\n\n<butler-context>\n<routing>匹配技能: {} (置信度: {:.0}%)</routing>\n<system-note>系统检测到用户的意图与已注册技能高度相关,请在回答中充分利用该技能的能力。</system-note>\n</butler-context>",
|
||||
skill_id,
|
||||
xml_escape(skill_id),
|
||||
hint.confidence * 100.0
|
||||
);
|
||||
}
|
||||
@@ -233,13 +249,13 @@ impl ButlerRouterMiddleware {
|
||||
}
|
||||
|
||||
let skill_info = hint.skill_id.as_ref().map_or(String::new(), |id| {
|
||||
format!("\n<skill>{}</skill>", id)
|
||||
format!("\n<skill>{}</skill>", xml_escape(id))
|
||||
});
|
||||
|
||||
format!(
|
||||
"\n\n<butler-context>\n<routing confidence=\"{:.0}%\">{}</routing>{}<system-note>以上是管家系统对您当前意图的分析。在对话中自然运用这些信息,主动提供有帮助的建议。</system-note>\n</butler-context>",
|
||||
hint.confidence * 100.0,
|
||||
domain_context,
|
||||
xml_escape(domain_context),
|
||||
skill_info
|
||||
)
|
||||
}
|
||||
@@ -251,6 +267,15 @@ impl Default for ButlerRouterMiddleware {
|
||||
}
|
||||
}
|
||||
|
||||
/// Escape XML special characters in user/admin-provided content to prevent
|
||||
/// breaking the `<butler-context>` XML structure.
|
||||
fn xml_escape(s: &str) -> String {
|
||||
s.replace('&', "&")
|
||||
.replace('<', "<")
|
||||
.replace('>', ">")
|
||||
.replace('"', """)
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AgentMiddleware for ButlerRouterMiddleware {
|
||||
fn name(&self) -> &str {
|
||||
|
||||
Reference in New Issue
Block a user