CVE-2024-39934: Insufficient Information (NVD-CWE-noinfo)
value: Robotmk before 2.0.1 allows a local user to escalate privileges (e.g., to SYSTEM) if automated Python environment setup is enabled, because the "shared holotree usage" feature allows any user to edit any Python environment.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-07-04T19:15Z
Repository: https://github.com/elabit/robotmk
Language: Rust
Files changed: src/bin/scheduler/setup/rcc.rs, src/results.rs, tests/test_scheduler.rs
Commit date: 2024-06-25 13:02:39 +0200
Commit message: don't enable shared holotrees

CMK-17546

Diff: diff --git a/src/bin/scheduler/setup/rcc.rs b/src/bin/scheduler/setup/rcc.rs
index 23236c6..a6089a9 100644
--- a/src/bin/scheduler/setup/rcc.rs
+++ b/src/bin/scheduler/setup/rcc.rs
@@ -153,21 +153,10 @@ fn rcc_setup(
             "Dropping the following plans due to long path support enabling failure: {}",
             failed_plan_ids_human_readable(rcc_setup_failures.long_path_support.keys())
         );
     }
 
-    debug!("Initializing shared holotree");
-    (sucessful_plans, rcc_setup_failures.shared_holotree) =
-        shared_holotree_init(global_config, sucessful_plans)
-            .context("Received termination signal while initializing shared holotree")?;
-    if !rcc_setup_failures.shared_holotree.is_empty() {
-        error!(
-            "Dropping the following plans due to shared holotree initialization failure: {}",
-            failed_plan_ids_human_readable(rcc_setup_failures.shared_holotree.keys())
-        );
-    }
-
     debug!("Initializing holotree");
     (sucessful_plans, rcc_setup_failures.holotree_init) =
         holotree_init(global_config, sucessful_plans)
             .context("Received termination signal while initializing holotree")?;
     if !rcc_setup_failures.holotree_init.is_empty() {
@@ -269,25 +258,10 @@ fn enable_long_path_support(
         &command_spec,
         "long_path_support_enabling",
     )
 }
 
-fn shared_holotree_init(
-    global_config: &GlobalConfig,
-    plans: Vec<Plan>,
-) -> Result<(Vec<Plan>, HashMap<String, String>), Cancelled> {
-    let mut command_spec =
-        RCCEnvironment::bundled_command_spec(&global_config.rcc_config.binary_path);
-    command_spec.add_arguments(["holotree", "shared", "--enable", "--once"]);
-    run_command_spec_once_in_current_session(
-        global_config,
-        plans,
-        &command_spec,
-        "shared_holotree_init",
-    )
-}
-
 fn holotree_init(
     global_config: &GlobalConfig,
     plans: Vec<Plan>,
 ) -> Result<(Vec<Plan>, HashMap<String, String>), Cancelled> {
     let mut command_spec =
diff --git a/src/results.rs b/src/results.rs
index 2a2eb5a..067053f 100644
--- a/src/results.rs
+++ b/src/results.rs
@@ -38,11 +38,10 @@ pub struct RCCSetupFailures {
     pub binary_permissions: HashMap<String, String>,
     pub profile_permissions: HashMap<String, String>,
     pub telemetry_disabling: HashMap<String, String>,
     pub profile_configuring: HashMap<String, String>,
     pub long_path_support: HashMap<String, String>,
-    pub shared_holotree: HashMap<String, String>,
     pub holotree_init: HashMap<String, String>,
 }
 
 impl WriteSection for RCCSetupFailures {
     fn name() -> &'static str {
diff --git a/tests/test_scheduler.rs b/tests/test_scheduler.rs
index 571c105..d437dc5 100644
--- a/tests/test_scheduler.rs
+++ b/tests/test_scheduler.rs
@@ -232,12 +232,10 @@ async fn assert_working_directory(
             &format!("holotree_initialization_user_{headed_user_name}.exit_code"),
             &format!("holotree_initialization_user_{headed_user_name}.stderr"),
             &format!("holotree_initialization_user_{headed_user_name}.stdout"),
             "long_path_support_enabling.stderr",
             "long_path_support_enabling.stdout",
-            "shared_holotree_init.stderr",
-            "shared_holotree_init.stdout",
             "telemetry_disabling_current_user.stderr",
             "telemetry_disabling_current_user.stdout",
             &format!("telemetry_disabling_user_{headed_user_name}.bat"),
             &format!("telemetry_disabling_user_{headed_user_name}.exit_code"),
             &format!("telemetry_disabling_user_{headed_user_name}.stderr"),
@@ -327,12 +325,10 @@ async fn assert_rcc_configuration(rcc_config: &RCCConfig) -> AnyhowResult<()> {
     rcc_config_diag_command
         .arg("configuration")
         .arg("diagnostics");
     let stdout = String::from_utf8(rcc_config_diag_command.output().await?.stdout)?;
     assert!(stdout.contains("telemetry-enabled                     ...  \"false\""));
-    assert!(stdout.contains("holotree-shared                       ...  \"true\""));
-    assert!(stdout.contains("holotree-global-shared                ...  \"true\""));
     if let RCCProfileConfig::Custom(custom_rcc_profile_config) = &rcc_config.profile_config {
         assert!(stdout.contains(&format!(
             "config-active-profile                 ...  \"{}\"",
             custom_rcc_profile_config.name
         )));

Vulnerable code:     debug!("Initializing shared holotree");
    (sucessful_plans, rcc_setup_failures.shared_holotree) =
        shared_holotree_init(global_config, sucessful_plans)
            .context("Received termination signal while initializing shared holotree")?;
    if !rcc_setup_failures.shared_holotree.is_empty() {
        error!(
            "Dropping the following plans due to shared holotree initialization failure: {}",
            failed_plan_ids_human_readable(rcc_setup_failures.shared_holotree.keys())
        );
    }

fn shared_holotree_init(
    global_config: &GlobalConfig,
    plans: Vec<Plan>,
) -> Result<(Vec<Plan>, HashMap<String, String>), Cancelled> {
    let mut command_spec =
        RCCEnvironment::bundled_command_spec(&global_config.rcc_config.binary_path);
    command_spec.add_arguments(["holotree", "shared", "--enable", "--once"]);
    run_command_spec_once_in_current_session(
        global_config,
        plans,
        &command_spec,
        "shared_holotree_init",
    )
}

    pub shared_holotree: HashMap<String, String>,
            "shared_holotree_init.stderr",
            "shared_holotree_init.stdout",
    assert!(stdout.contains("holotree-shared                       ...  \"true\""));
    assert!(stdout.contains("holotree-global-shared                ...  \"true\""));