fix(security): P0 审计修复 — 6项关键安全/编译问题
F1: kernel.rs multi-agent 编译错误 — 重排 spawn_agent 中 A2A 注册顺序,
在 config 被 registry.register() 消费前使用
F2: saas-config.toml 从 git 追踪中移除 — 包含数据库密码已进入版本历史
F3: config.rs 硬编码开发密钥改用 #[cfg(debug_assertions)] 编译时门控 —
dev fallback 密钥不再进入 release 构建
F4: 公共认证端点添加 IP 速率限制 (20 RPM) — 防止暴力破解
F5: SSE relay 路由分离出全局 15s TimeoutLayer — 避免长流式响应被截断
F6: Provider API 密钥入库前 AES-256-GCM 加密 — 明文存储修复
附带:完整审计报告 docs/superpowers/specs/2026-03-30-comprehensive-audit-report.md
This commit is contained in:
@@ -2,7 +2,10 @@
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use secrecy::{ExposeSecret, SecretString};
|
||||
use secrecy::SecretString;
|
||||
#[cfg(not(debug_assertions))]
|
||||
use secrecy::ExposeSecret;
|
||||
#[cfg(not(debug_assertions))]
|
||||
use sha2::Digest;
|
||||
|
||||
/// SaaS 服务器完整配置
|
||||
@@ -226,21 +229,20 @@ impl SaaSConfig {
|
||||
/// 获取 JWT 密钥 (从环境变量或生成临时值)
|
||||
/// 生产环境必须设置 ZCLAW_SAAS_JWT_SECRET
|
||||
pub fn jwt_secret(&self) -> anyhow::Result<SecretString> {
|
||||
let is_dev = std::env::var("ZCLAW_SAAS_DEV")
|
||||
.map(|v| v == "true" || v == "1")
|
||||
.unwrap_or(false);
|
||||
|
||||
match std::env::var("ZCLAW_SAAS_JWT_SECRET") {
|
||||
Ok(secret) => Ok(SecretString::from(secret)),
|
||||
Err(_) => {
|
||||
if is_dev {
|
||||
// 开发 fallback 密钥仅在 debug 构建中可用,不会进入 release
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
tracing::warn!("ZCLAW_SAAS_JWT_SECRET not set, using development default (INSECURE)");
|
||||
Ok(SecretString::from("zclaw-dev-only-secret-do-not-use-in-prod".to_string()))
|
||||
} else {
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
anyhow::bail!(
|
||||
"ZCLAW_SAAS_JWT_SECRET 环境变量未设置。\
|
||||
请设置一个强随机密钥 (至少 32 字符)。\
|
||||
开发环境可设置 ZCLAW_SAAS_DEV=true 使用默认值。"
|
||||
请设置一个强随机密钥 (至少 32 字符)。"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -256,10 +258,6 @@ impl SaaSConfig {
|
||||
/// 从 ZCLAW_TOTP_ENCRYPTION_KEY 环境变量加载 (hex 编码的 64 字符)
|
||||
/// 开发环境使用默认值 (不安全)
|
||||
pub fn totp_encryption_key(&self) -> anyhow::Result<[u8; 32]> {
|
||||
let is_dev = std::env::var("ZCLAW_SAAS_DEV")
|
||||
.map(|v| v == "true" || v == "1")
|
||||
.unwrap_or(false);
|
||||
|
||||
match std::env::var("ZCLAW_TOTP_ENCRYPTION_KEY") {
|
||||
Ok(hex_key) => {
|
||||
if hex_key.len() != 64 {
|
||||
@@ -273,13 +271,16 @@ impl SaaSConfig {
|
||||
Ok(key)
|
||||
}
|
||||
Err(_) => {
|
||||
if is_dev {
|
||||
// 开发环境: 仅在 debug 构建中使用固定密钥
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
tracing::warn!("ZCLAW_TOTP_ENCRYPTION_KEY not set, using development default (INSECURE)");
|
||||
// 开发环境使用固定密钥
|
||||
let mut key = [0u8; 32];
|
||||
key.copy_from_slice(b"zclaw-dev-totp-encrypt-key-32b!x");
|
||||
Ok(key)
|
||||
} else {
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
// 生产环境: 使用 JWT 密钥的 SHA-256 哈希作为加密密钥
|
||||
tracing::warn!("ZCLAW_TOTP_ENCRYPTION_KEY not set, deriving from JWT secret");
|
||||
let jwt = self.jwt_secret()?;
|
||||
|
||||
Reference in New Issue
Block a user