diff --git a/crates/settings/tests/common/mod.rs b/crates/settings/tests/common/mod.rs
--- a/crates/settings/tests/common/mod.rs
+++ b/crates/settings/tests/common/mod.rs
@@ -94,3 +94,21 @@ pub fn write_config(dir: &Path, text: &str) {
 pub fn read_config(dir: &Path) -> String {
     std::fs::read_to_string(config_path(dir)).unwrap()
 }
+
+#[cfg(unix)]
+pub fn restrict_directory_writes(dir: &Path) -> bool {
+    use std::os::unix::fs::PermissionsExt;
+
+    let permissions = std::fs::metadata(dir).unwrap().permissions();
+    std::fs::set_permissions(dir, std::fs::Permissions::from_mode(0o500)).unwrap();
+    match tempfile::NamedTempFile::new_in(dir) {
+        Ok(probe) => {
+            drop(probe);
+            std::fs::set_permissions(dir, permissions).unwrap();
+            eprintln!("skipping permission test: environment permits writes into a 0500 directory");
+            false
+        }
+        Err(error) if error.kind() == std::io::ErrorKind::PermissionDenied => true,
+        Err(error) => panic!("unexpected directory write-probe failure: {error}"),
+    }
+}
diff --git a/crates/settings/tests/paths.rs b/crates/settings/tests/paths.rs
--- a/crates/settings/tests/paths.rs
+++ b/crates/settings/tests/paths.rs
@@ -134,7 +134,9 @@ fn unwritable_folder_is_reported_at_open_not_first_save() {
     let tmp = tempfile::tempdir().unwrap();
     let dir = tmp.path().join("ro");
     std::fs::create_dir(&dir).unwrap();
-    std::fs::set_permissions(&dir, std::fs::Permissions::from_mode(0o500)).unwrap();
+    if !common::restrict_directory_writes(&dir) {
+        return;
+    }
     let (mut store, report) = open_in(&dir);
     std::fs::set_permissions(&dir, std::fs::Permissions::from_mode(0o700)).unwrap();
     assert!(store.is_read_only());
diff --git a/crates/settings/tests/recovery.rs b/crates/settings/tests/recovery.rs
--- a/crates/settings/tests/recovery.rs
+++ b/crates/settings/tests/recovery.rs
@@ -77,9 +77,10 @@ fn damaged_file_that_cannot_be_moved_is_left_alone() {
     use std::os::unix::fs::PermissionsExt;
     let tmp = tempfile::tempdir().unwrap();
     write_config(tmp.path(), "not = [toml");
-    // The folder passes the write probe only while it is writable, so open first, then lock it.
     let dir = tmp.path();
-    std::fs::set_permissions(dir, std::fs::Permissions::from_mode(0o500)).unwrap();
+    if !common::restrict_directory_writes(dir) {
+        return;
+    }
     let (mut store, report) = open_in(dir);
     std::fs::set_permissions(dir, std::fs::Permissions::from_mode(0o700)).unwrap();
     assert!(store.is_read_only(), "{report:?}");
@@ -152,7 +153,9 @@ fn failed_migration_in_an_unwritable_folder_shows_defaults() {
     let tmp = tempfile::tempdir().unwrap();
     // Version 0 has no migration step, so upgrading fails.
     write_config(tmp.path(), "schema_version = 0\n[general]\nlanguage = \"de\"\n");
-    std::fs::set_permissions(tmp.path(), std::fs::Permissions::from_mode(0o500)).unwrap();
+    if !common::restrict_directory_writes(tmp.path()) {
+        return;
+    }
     let (store, report) = open_in(tmp.path());
     std::fs::set_permissions(tmp.path(), std::fs::Permissions::from_mode(0o700)).unwrap();
     assert!(matches!(report.read_only, Some(ReadOnlyReason::DirNotWritable(_))), "{report:?}");
diff --git a/crates/settings/tests/store.rs b/crates/settings/tests/store.rs
--- a/crates/settings/tests/store.rs
+++ b/crates/settings/tests/store.rs
@@ -204,6 +204,14 @@ fn read_only_file_makes_the_save_fail_visibly() {
     let (mut store, _) = open_in(tmp.path());
     store.flush().unwrap();
     std::fs::set_permissions(config_path(tmp.path()), std::fs::Permissions::from_mode(0o400)).unwrap();
+    match std::fs::File::options().write(true).open(config_path(tmp.path())) {
+        Ok(_) => {
+            eprintln!("skipping permission test: environment permits writes into a 0400 file");
+            return;
+        }
+        Err(error) if error.kind() == std::io::ErrorKind::PermissionDenied => {}
+        Err(error) => panic!("unexpected file write-probe failure: {error}"),
+    }
     store.update(|p| p.general.language = "fr".into());
     let r = store.tick(Instant::now() + Duration::from_secs(1));
     assert!(matches!(r.status, SaveStatus::Failed(craft_settings::SettingsError::Io(_))), "{r:?}");
