fix: harden cloud storage security

This commit is contained in:
237899745
2026-06-13 18:45:12 +08:00
parent 7943b04ee2
commit bb6ad01018
28 changed files with 2229 additions and 996 deletions

View File

@@ -693,7 +693,7 @@ dependencies = [
[[package]]
name = "desktop-client"
version = "0.1.30"
version = "0.1.31"
dependencies = [
"reqwest 0.12.28",
"rusqlite",

View File

@@ -1,6 +1,6 @@
[package]
name = "desktop-client"
version = "0.1.30"
version = "0.1.31"
description = "A Tauri App"
authors = ["you"]
edition = "2021"

View File

@@ -1,4 +1,4 @@
use reqwest::Method;
use reqwest::{Method, Url};
use reqwest::StatusCode;
use rusqlite::{params, Connection};
use serde::Serialize;
@@ -454,6 +454,49 @@ fn is_update_installer_file_name(file_name: &str) -> bool {
lower.starts_with("wanwan-cloud-desktop_v") || file_name.trim().starts_with("玩玩云_v")
}
fn ensure_http_download_url(raw_url: &str) -> Result<(), String> {
let parsed = Url::parse(raw_url).map_err(|_| "下载地址格式无效".to_string())?;
match parsed.scheme() {
"http" | "https" => Ok(()),
_ => Err("仅允许 HTTP/HTTPS 下载地址".to_string()),
}
}
fn validate_update_installer_path(installer_path: &str) -> Result<PathBuf, String> {
let path_text = installer_path.trim();
if path_text.is_empty() {
return Err("安装包路径不能为空".to_string());
}
let installer = PathBuf::from(path_text);
if !installer.exists() {
return Err("安装包不存在,请重新下载".to_string());
}
if !installer.is_file() {
return Err("安装包路径无效".to_string());
}
let file_name = installer
.file_name()
.and_then(|name| name.to_str())
.ok_or_else(|| "安装包文件名无效".to_string())?;
if !is_update_installer_file_name(file_name) {
return Err("仅允许启动玩玩云官方更新安装包".to_string());
}
let download_dir = resolve_download_dir()
.canonicalize()
.map_err(|err| format!("读取下载目录失败: {}", err))?;
let canonical_installer = installer
.canonicalize()
.map_err(|err| format!("读取安装包路径失败: {}", err))?;
if !canonical_installer.starts_with(&download_dir) {
return Err("安装包必须位于系统下载目录内".to_string());
}
Ok(canonical_installer)
}
fn cleanup_old_update_installers(
download_dir: &Path,
keep_file_name: &str,
@@ -1192,6 +1235,7 @@ async fn api_native_download(
if trimmed_url.is_empty() {
return Err("下载地址不能为空".to_string());
}
ensure_http_download_url(&trimmed_url)?;
let preferred_name = file_name
.as_deref()
@@ -1418,18 +1462,8 @@ fn api_compute_file_sha256(file_path: String) -> Result<BridgeResponse, String>
#[tauri::command]
fn api_launch_installer(installer_path: String) -> Result<BridgeResponse, String> {
let path_text = installer_path.trim().to_string();
if path_text.is_empty() {
return Err("安装包路径不能为空".to_string());
}
let installer = PathBuf::from(&path_text);
if !installer.exists() {
return Err("安装包不存在,请重新下载".to_string());
}
if !installer.is_file() {
return Err("安装包路径无效".to_string());
}
let installer = validate_update_installer_path(&installer_path)?;
let path_text = installer.to_string_lossy().to_string();
#[cfg(target_os = "windows")]
let spawn_result = Command::new(&installer).spawn();
@@ -1456,18 +1490,8 @@ fn api_launch_installer(installer_path: String) -> Result<BridgeResponse, String
#[tauri::command]
fn api_silent_install_and_restart(installer_path: String) -> Result<BridgeResponse, String> {
let path_text = installer_path.trim().to_string();
if path_text.is_empty() {
return Err("安装包路径不能为空".to_string());
}
let installer = PathBuf::from(&path_text);
if !installer.exists() {
return Err("安装包不存在,请重新下载".to_string());
}
if !installer.is_file() {
return Err("安装包路径无效".to_string());
}
let installer = validate_update_installer_path(&installer_path)?;
let path_text = installer.to_string_lossy().to_string();
#[cfg(target_os = "windows")]
let windows_log_file_path: String;

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "玩玩云",
"version": "0.1.30",
"version": "0.1.31",
"identifier": "cn.workyai.wanwancloud.desktop",
"build": {
"beforeDevCommand": "npm run dev",
@@ -20,7 +20,7 @@
}
],
"security": {
"csp": null
"csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self' http://127.0.0.1:* http://localhost:* https:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'"
}
},
"bundle": {