fix: harden cloud storage security
This commit is contained in:
2
desktop-client/src-tauri/Cargo.lock
generated
2
desktop-client/src-tauri/Cargo.lock
generated
@@ -693,7 +693,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "desktop-client"
|
||||
version = "0.1.30"
|
||||
version = "0.1.31"
|
||||
dependencies = [
|
||||
"reqwest 0.12.28",
|
||||
"rusqlite",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "desktop-client"
|
||||
version = "0.1.30"
|
||||
version = "0.1.31"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user