Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 50 additions & 12 deletions cmd/soroban-cli/src/config/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,15 +416,18 @@ impl Args {
#[cfg(unix)]
{
use std::io::Write as _;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
let mut to_file = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.mode(0o600)
.open(&path)?;
to_file.write_all(content.as_bytes())?;
fix_config_permissions();
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o600))?;
if let Ok(root) = self.config_dir() {
fix_config_permissions(root);
}
}

#[cfg(not(unix))]
Expand Down Expand Up @@ -528,13 +531,9 @@ impl Pwd for Args {
}

#[cfg(unix)]
fn fix_config_permissions() {
fn fix_config_permissions(root: std::path::PathBuf) {
use std::os::unix::fs::PermissionsExt;

let Ok(root) = global_config_path() else {
return;
};

let mut bad_dirs = Vec::new();
let mut bad_files = Vec::new();
let mut stack = vec![root];
Expand Down Expand Up @@ -591,7 +590,7 @@ pub fn ensure_directory(dir: PathBuf) -> Result<PathBuf, Error> {
.mode(0o700)
.create(parent)
.map_err(|_| dir_creation_failed(parent))?;
fix_config_permissions();
fix_config_permissions(parent.to_path_buf());
Comment thread
fnando marked this conversation as resolved.
}

#[cfg(not(unix))]
Expand Down Expand Up @@ -632,9 +631,6 @@ impl KeyType {
path: path.to_path_buf(),
})?;

#[cfg(unix)]
fix_config_permissions();

Ok(toml::from_str(&data)?)
}

Expand Down Expand Up @@ -701,7 +697,16 @@ impl KeyType {
})?;

#[cfg(unix)]
fix_config_permissions();
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&filepath, std::fs::Permissions::from_mode(0o600)).map_err(
|error| Error::IdCreationFailed {
filepath: filepath.clone(),
error,
},
)?;
fix_config_permissions(pwd.to_path_buf());
}

Ok(filepath)
}
Expand Down Expand Up @@ -848,6 +853,39 @@ mod tests {
use serial_test::serial;
use std::collections::HashMap;

#[test]
fn overwrite_resets_file_permissions_to_0600() {
use std::os::unix::fs::PermissionsExt;

let dir = tempfile::tempdir().unwrap();
let identity_dir = dir.path().join("identity");
std::fs::create_dir_all(&identity_dir).unwrap();

// Pre-create alice.toml at 0644 to simulate an inherited insecure mode.
let alice = identity_dir.join("alice.toml");
std::fs::write(&alice, "seed_phrase = \"old\"\n").unwrap();
std::fs::set_permissions(&alice, std::fs::Permissions::from_mode(0o644)).unwrap();

assert_eq!(
std::fs::metadata(&alice).unwrap().permissions().mode() & 0o777,
0o644,
"setup: alice.toml should start at 0644"
);

let value: HashMap<String, String> = HashMap::new();
KeyType::Identity
.write("alice", &value, dir.path())
.unwrap();

let perms = std::fs::metadata(&alice).unwrap().permissions();
assert_eq!(
perms.mode() & 0o777,
0o600,
"overwritten identity file should be 0600, got {:o}",
perms.mode() & 0o777
);
}

#[test]
fn test_write_sets_file_permissions_to_0600() {
use std::os::unix::fs::PermissionsExt;
Expand Down
Loading