fix: 安全漏洞修复 — CLI密码泄露 + margin上限 + 路径检查 + CSP/限速
CRITICAL: - CLI --password 未提供时自动从 QRGEN_WIFI_PASSWORD 环境变量读取 避免密码出现在 ps aux / /proc/pid/cmdline 进程列表中 HIGH: - unsafe from_utf8_unchecked SAFETY 注释增强, 详细解释为何有效 - CLI --margin 添加 value_parser range(0..=100), 防止 u8=255 导致内存爆炸 - Web CORS permissive 添加注释说明公开 API 设计理由 - GUI FS 权限收紧: 写权限从 /c/Users/33644/** 限制为 Downloads/Documents/Desktop/AppData MEDIUM: - 新增 QrError::InvalidEcLevel(String), 不再复用 InvalidVersion(0) - --logo/--batch/--output_dir 均添加 check_path() 路径遍历检查 - Web 添加 tower::limit::ConcurrencyLimitLayer(10) 并发限制防 CPU 耗尽 - decode_image 添加 4096x4096 图片尺寸上限防解压炸弹 LOW: - Web 添加 Content-Security-Policy 响应头
This commit is contained in:
+17
-3
@@ -56,7 +56,7 @@ struct EncodeOpts {
|
||||
version: Option<u8>,
|
||||
#[arg(short = 's', long, default_value = "4", value_parser = clap::value_parser!(u8).range(1..=20))]
|
||||
size: u8,
|
||||
#[arg(short = 'm', long, default_value = "4")]
|
||||
#[arg(short = 'm', long, default_value = "4", value_parser = clap::value_parser!(u8).range(0..=100))]
|
||||
margin: u8,
|
||||
#[arg(long)] fg: Option<String>,
|
||||
#[arg(long)] bg: Option<String>,
|
||||
@@ -64,7 +64,7 @@ struct EncodeOpts {
|
||||
#[arg(short = 'f', long, default_value = "png")]
|
||||
format: String,
|
||||
#[arg(long)] mode: Option<String>,
|
||||
// WiFi
|
||||
// WiFi — 密码优先从环境变量 QRGEN_WIFI_PASSWORD 读取,避免命令行泄露
|
||||
#[arg(long)] ssid: Option<String>,
|
||||
#[arg(long)] password: Option<String>,
|
||||
#[arg(long, default_value = "WPA")]
|
||||
@@ -174,12 +174,20 @@ fn cmd_encode(content: &str, output: &Option<String>, opts: &EncodeOpts) -> Resu
|
||||
let final_text = if let Some(m) = &opts.mode {
|
||||
build_mode(m, opts, &text)?
|
||||
} else if let Some(ref bf) = opts.batch {
|
||||
check_path(bf)?; // 批量文件路径检查
|
||||
if let Some(od) = &opts.output_dir {
|
||||
check_path(od)?; // 输出目录路径检查
|
||||
}
|
||||
return do_batch(bf, opts);
|
||||
} else {
|
||||
text
|
||||
};
|
||||
|
||||
let level: EcLevel = opts.level.parse().map_err(|e: String| anyhow::anyhow!(e))?;
|
||||
// --logo 文件路径也需安全检查
|
||||
if let Some(logo_path) = &opts.logo {
|
||||
check_path(logo_path)?;
|
||||
}
|
||||
let logo = opts
|
||||
.logo
|
||||
.as_ref()
|
||||
@@ -252,9 +260,15 @@ fn build_mode(mode: &str, opts: &EncodeOpts, fb: &str) -> Result<String> {
|
||||
.ssid
|
||||
.as_deref()
|
||||
.ok_or_else(|| anyhow::anyhow!("WiFi 模式需要 --ssid"))?;
|
||||
// 密码优先从 --password 读取,未提供时尝试环境变量 QRGEN_WIFI_PASSWORD
|
||||
let pwd = opts
|
||||
.password
|
||||
.as_deref()
|
||||
.or_else(|| std::env::var("QRGEN_WIFI_PASSWORD").ok().as_deref())
|
||||
.unwrap_or("");
|
||||
Ok(text_builder::build_wifi_text(
|
||||
s,
|
||||
opts.password.as_deref().unwrap_or(""),
|
||||
pwd,
|
||||
&opts.encryption,
|
||||
opts.hidden,
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user