CVE-2021-3917: Incorrect Default Permissions (CWE-276)
value: A flaw was found in the coreos-installer, where it writes the Ignition config to the target system with world-readable access permissions. This flaw allows a local attacker to have read access to potentially sensitive data. The highest threat from this vulnerability is to confidentiality.
CWE description: During installation, installed file permissions are set to allow anyone to modify those files.
CVSS v3 base score: 5.5
Published: 2022-08-23T20:15Z
Repository: https://github.com/coreos/coreos-installer
Language: Rust
Files changed: src/install.rs
Commit date: 2021-07-07 15:56:12 -0400
Commit message: install: restrict access permissions on /boot/ignition{,/config.ign}

The Ignition config may contain secrets.  Don't expose it, or anything in
its parent directory, to unprivileged processes.

https://github.com/coreos/fedora-coreos-tracker/issues/889

Diff: diff --git a/src/install.rs b/src/install.rs
index 20d1f41..3640723 100644
--- a/src/install.rs
+++ b/src/install.rs
@@ -14,13 +14,15 @@
 
 use anyhow::{bail, Context, Result};
 use lazy_static::lazy_static;
 use nix::mount;
 use regex::Regex;
-use std::fs::{copy as fscopy, create_dir_all, read_dir, File, OpenOptions};
+use std::fs::{
+    copy as fscopy, create_dir_all, read_dir, set_permissions, File, OpenOptions, Permissions,
+};
 use std::io::{copy, Read, Seek, SeekFrom, Write};
-use std::os::unix::fs::FileTypeExt;
+use std::os::unix::fs::{FileTypeExt, PermissionsExt};
 use std::path::{Path, PathBuf};
 
 use crate::blockdev::*;
 use crate::cmdline::*;
 use crate::download::*;
@@ -246,11 +248,25 @@ fn write_ignition(
     };
 
     // make parent directory
     let mut config_dest = mountpoint.to_path_buf();
     config_dest.push("ignition");
-    create_dir_all(&config_dest).context("creating Ignition config directory")?;
+    if !config_dest.is_dir() {
+        create_dir_all(&config_dest).with_context(|| {
+            format!(
+                "creating Ignition config directory {}",
+                config_dest.display()
+            )
+        })?;
+        // Ignition data may contain secrets; restrict to root
+        set_permissions(&config_dest, Permissions::from_mode(0o700)).with_context(|| {
+            format!(
+                "setting file mode for Ignition directory {}",
+                config_dest.display()
+            )
+        })?;
+    }
 
     // do the copy
     config_dest.push("config.ign");
     let mut config_out = OpenOptions::new()
         .write(true)
@@ -260,10 +276,17 @@ fn write_ignition(
             format!(
                 "opening destination Ignition config {}",
                 config_dest.display()
             )
         })?;
+    // Ignition config may contain secrets; restrict to root
+    set_permissions(&config_dest, Permissions::from_mode(0o600)).with_context(|| {
+        format!(
+            "setting file mode for destination Ignition config {}",
+            config_dest.display()
+        )
+    })?;
     copy(&mut config_in, &mut config_out).context("writing Ignition config")?;
 
     Ok(())
 }
 

Vulnerable code: use std::fs::{copy as fscopy, create_dir_all, read_dir, File, OpenOptions};
use std::os::unix::fs::FileTypeExt;
    create_dir_all(&config_dest).context("creating Ignition config directory")?;
Fixed code: use std::fs::{
    copy as fscopy, create_dir_all, read_dir, set_permissions, File, OpenOptions, Permissions,
};
use std::os::unix::fs::{FileTypeExt, PermissionsExt};
    if !config_dest.is_dir() {
        create_dir_all(&config_dest).with_context(|| {
            format!(
                "creating Ignition config directory {}",
                config_dest.display()
            )
        })?;
        // Ignition data may contain secrets; restrict to root
        set_permissions(&config_dest, Permissions::from_mode(0o700)).with_context(|| {
            format!(
                "setting file mode for Ignition directory {}",
                config_dest.display()
            )
        })?;
    }
    // Ignition config may contain secrets; restrict to root
    set_permissions(&config_dest, Permissions::from_mode(0o600)).with_context(|| {
        format!(
            "setting file mode for destination Ignition config {}",
            config_dest.display()
        )
    })?;