Skip to content

Commit cf49ab2

Browse files
Fixes pentest issue DG25-28 from 2025-09-02 (#578)
* ensure data directories have appropriate permissions * also set permissions for log directory * set permissions for other files/directories * automatically determine if path is a directory * nix flake update
1 parent 060b60a commit cf49ab2

5 files changed

Lines changed: 47 additions & 20 deletions

File tree

flake.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/src/app_config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use struct_patch::Patch;
99
use strum::{Display, EnumString};
1010
use tauri::{AppHandle, Manager};
1111

12+
use crate::set_perms;
13+
1214
static APP_CONFIG_FILE_NAME: &str = "config.json";
1315

1416
fn get_config_file_path(app: &AppHandle) -> PathBuf {
@@ -19,7 +21,9 @@ fn get_config_file_path(app: &AppHandle) -> PathBuf {
1921
if !config_file_path.exists() {
2022
create_dir_all(&config_file_path).expect("Failed to create missing app data dir");
2123
}
24+
set_perms(&config_file_path);
2225
config_file_path.push(APP_CONFIG_FILE_NAME);
26+
set_perms(&config_file_path);
2327
config_file_path
2428
}
2529

src-tauri/src/bin/defguard-client.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use defguard_client::{
1717
DB_POOL,
1818
},
1919
periodic::run_periodic_tasks,
20-
service,
20+
service, set_perms,
2121
tray::{configure_tray_icon, setup_tray, show_main_window},
2222
utils::load_log_targets,
2323
VERSION,
@@ -277,19 +277,22 @@ fn main() {
277277
app.run(|app_handle, event| match event {
278278
// Startup tasks
279279
RunEvent::Ready => {
280+
let data_dir = app_handle
281+
.path()
282+
.app_data_dir()
283+
.unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into());
284+
let log_dir = app_handle
285+
.path()
286+
.app_log_dir()
287+
.unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into());
288+
289+
// Ensure directories have appropriate permissions (dg25-28).
290+
set_perms(&data_dir);
291+
set_perms(&log_dir);
280292
info!(
281-
"Application data (database file) will be stored in: {} and application logs in: {}. \
293+
"Application data (database file) will be stored in: {data_dir:?} and application logs in: {log_dir:?}. \
282294
Logs of the background Defguard service responsible for managing VPN connections at the \
283295
network level will be stored in: {}.",
284-
// display the path to the app data directory, convert option<pathbuf> to option<&str>
285-
app_handle
286-
.path()
287-
.app_data_dir()
288-
.unwrap_or_else(|_| "UNDEFINED DATA DIRECTORY".into()).display(),
289-
app_handle
290-
.path()
291-
.app_log_dir()
292-
.unwrap_or_else(|_| "UNDEFINED LOG DIRECTORY".into()).display(),
293296
service::config::DEFAULT_LOG_DIR
294297
);
295298
tauri::async_runtime::block_on(startup(app_handle));

src-tauri/src/database/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
pub mod models;
2-
31
use std::{
42
env,
53
fs::{create_dir_all, File},
@@ -9,10 +7,12 @@ use std::{
97

108
use sqlx::sqlite::{SqliteAutoVacuum, SqliteConnectOptions, SqliteJournalMode, SqlitePool};
119

12-
use crate::{app_data_dir, error::Error};
10+
use crate::{app_data_dir, error::Error, set_perms};
1311

1412
const DB_NAME: &str = "defguard.db";
1513

14+
pub mod models;
15+
1616
pub(crate) type DbPool = SqlitePool;
1717

1818
pub static DB_POOL: LazyLock<SqlitePool> = LazyLock::new(|| {
@@ -59,6 +59,7 @@ fn prepare_db_url() -> Result<String, Error> {
5959
app_dir.to_string_lossy()
6060
);
6161
}
62+
set_perms(&app_dir);
6263
let db_path = app_dir.join(DB_NAME);
6364
if db_path.exists() {
6465
debug!(
@@ -77,6 +78,7 @@ fn prepare_db_url() -> Result<String, Error> {
7778
db_path.to_string_lossy()
7879
);
7980
}
81+
set_perms(&db_path);
8082
debug!(
8183
"Application's database file is located at: {}",
8284
db_path.to_string_lossy()

src-tauri/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// FIXME: actually refactor errors instead
22
#![allow(clippy::result_large_err)]
33
use std::{fmt, path::PathBuf};
4+
#[cfg(not(windows))]
5+
use std::{
6+
fs::{set_permissions, Permissions},
7+
os::unix::fs::PermissionsExt,
8+
};
49

510
use chrono::NaiveDateTime;
611
use semver::Version;
@@ -77,6 +82,19 @@ pub fn app_data_dir() -> Option<PathBuf> {
7782
dirs_next::data_dir().map(|dir| dir.join(BUNDLE_IDENTIFIER))
7883
}
7984

85+
/// Ensures path has appropriate permissions set (dg25-28):
86+
/// - 700 for directories
87+
/// - 600 for files
88+
pub fn set_perms(path: &PathBuf) {
89+
#[cfg(not(windows))]
90+
{
91+
let perms = if path.is_dir() { 0o700 } else { 0o600 };
92+
if let Err(err) = set_permissions(path, Permissions::from_mode(perms)) {
93+
warn!("Failed to set permissions on path {path:?}: {err}");
94+
}
95+
}
96+
}
97+
8098
/// Location type used in commands to check if we using tunnel or location
8199
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
82100
pub enum ConnectionType {

0 commit comments

Comments
 (0)