CVE-2026-104795CWE-250

CVE-2026-104795

High · published October 14, 2026

CVSS v3.1
8.8
EPSS
0%
Percentile
6.0
In the wild
Unconfirmed
What it is

The insights-runtime-extractor runs as a privileged DaemonSet (`hostPID: true`)

that scans container processes for runtime fingerprinting. When scanning a

container, the coordinator:

1. **fork()s** a child process

2. **setns()** into the target container's PID and mount namespaces

3. **fchdir()** back to an orphaned FD pointing at the extractor's own root

filesystem (where `/crio.sock` is hostPath-mounted)

4. Calls **only `seteuid(target_uid)`** — changing the effective UID but leaving

the **real UID and saved-set-UID at 0** and **retaining the permitted

capability set**

5. The `check_no_privileged_perms()` guard inspects only the Effective capability

set (so it passes), and is **skipped entirely when the target runs as uid 0**

6. The `VersionExecutable` fingerprint invokes `fpr_kind_executable` with

`process.command_line[0]` — the target's argv[0], read from

`/proc/<pid>/cmdline` and **fully controlled by the workload**

7. `fpr_kind_executable` calls `exec.Command(executable, "--version").Output()`

— executing the **workload's own binary** inside the workload's mount

namespace while **ruid=0 in the host user namespace**

The executed process can call `setuid(0)` to restore full root with

`CAP_SYS_ADMIN`, and inherits the orphaned cwd which resolves into the extractor

container's filesystem containing the host CRI-O socket.

## Affected Code

### 1. Insufficient privilege drop (Rust — extractor coordinator)

**File:** `extractor/src/insights_runtime_extractor.rs`

```rust

// Lines 139-146 — seteuid-only drop, guard skipped for root containers

join_process_namespaces(process.pid)?;

change_dir(current_dir);

switch_user(*process.uid)?;

if *process.uid != 0 {

perms::check_no_privileged_perms()

.expect("Must not have privileged permissions to run fingerprints");

}

fingerprint::run_fingerprints(&config, out_dir, &process);

```

```rust

// Lines 182-185 — only effective UID changed; ruid/suid stay 0

fn switch_user(uid: u32) -> Result<(), ScannerError> {

debug!("... Becoming user: {uid}");

seteuid(uid.into()).map_err(|e| ScannerError::Errno(e))

}

```

### 2. Execution of untrusted binary (Go — fingerprint)

**File:** `fingerprints/pkg/utils/file.go`

```go

// Lines 75-80 — executes a path taken verbatim from workload's argv[0]

func GetExecutableVersionOutput(executable string) (string, error) {

out, err := exec.Command(executable, "--version").Output()

if err != nil {

return "", err

}

return string(out), nil

}

```

### 3. Workload-controlled path forwarded (Rust — version_executable)

**File:** `version_executable.rs`

```rust

// Lines 29-34 — workload-controlled command_line[0] forwarded to fingerprint

return Some(vec![

fpr_kind_executable,

out_dir.to_string(),

String::from(&process.command_line[0]),

String::from(&version_executable.runtime_kind_name),

]);

```

## Attack Pattern

**Attacker:** Any tenant able to schedule a pod (unprivileged, any namespace)

**Victim:** The node running the insights-runtime-extractor DaemonSet

**Trigger:** Automatic — the DaemonSet scans all container processes on the node

**Attack sequence:**

1. Attacker creates a pod whose process name matches a configured

versioned-executable pattern (`node`, `python`, `python3`, `MainThread`,

or contains `java`)

2. The pod's main binary (at the path matching argv[0]) is a malicious

executable that calls `setuid(0)` to restore root

3. When the insights operator triggers a scan, the DaemonSet forks, enters the

attacker's mount namespace, and executes the attacker's binary with ruid=0

4. The attacker's code regains full root with `CAP_SYS_ADMIN` in the host user

namespace

5. The inherited cwd contains the host CRI-O socket → full node compromise

The record
Technical detail
CVSS v3.1
8.8 · HIGH
Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
CVSS v4.0
Not supplied
EPSS
0.00170 · 6.0th percentile
Weakness
CWE-250 · Execution with Unnecessary Privileges
Published
2026-10-14T15:16Z
References (3)
EPSS history
Timeline
  • 16 OCT 03:27Z
    EPSS moved — → 0%
    epss
  • 14 OCT 10:55Z
    Insights-runtime-extractor: insights-runtime-extractor: container escape via privileged binary execution
    cvelistv5
  • 14 OCT 10:55Z
    Insights-runtime-extractor: insights-runtime-extractor: container escape via privileged binary execution
    cvelistv5