{"id":39014,"date":"2026-10-16T00:34:51","date_gmt":"2026-10-15T16:34:51","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-104795"},"modified":"2026-10-16T00:34:51","modified_gmt":"2026-10-15T16:34:51","slug":"cve-2026-104795","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-104795","title":{"rendered":"CVE-2026-104795 [HIGH] &#8211; The insights-runtime-extractor runs as a privileged DaemonSet (`hostPID: true`)\nthat scans"},"content":{"rendered":"<p>The insights-runtime-extractor runs as a privileged DaemonSet (`hostPID: true`)<br \/>\nthat scans container processes for runtime fingerprinting. When scanning a<br \/>\ncontainer, the coordinator:<\/p>\n<p>1. **fork()s** a child process<br \/>\n2. **setns()** into the target container&#8217;s PID and mount namespaces<br \/>\n3. **fchdir()** back to an orphaned FD pointing at the extractor&#8217;s own root<br \/>\n   filesystem (where `\/crio.sock` is hostPath-mounted)<br \/>\n4. Calls **only `seteuid(target_uid)`** \u2014 changing the effective UID but leaving<br \/>\n   the **real UID and saved-set-UID at 0** and **retaining the permitted<br \/>\n   capability set**<br \/>\n5. The `check_no_privileged_perms()` guard inspects only the Effective capability<br \/>\n   set (so it passes), and is **skipped entirely when the target runs as uid 0**<br \/>\n6. The `VersionExecutable` fingerprint invokes `fpr_kind_executable` with<br \/>\n   `process.command_line[0]` \u2014 the target&#8217;s argv[0], read from<br \/>\n   `\/proc\/\/cmdline` and **fully controlled by the workload**<br \/>\n7. `fpr_kind_executable` calls `exec.Command(executable, &#8220;&#8211;version&#8221;).Output()`<br \/>\n   \u2014 executing the **workload&#8217;s own binary** inside the workload&#8217;s mount<br \/>\n   namespace while **ruid=0 in the host user namespace**<\/p>\n<p>The executed process can call `setuid(0)` to restore full root with<br \/>\n`CAP_SYS_ADMIN`, and inherits the orphaned cwd which resolves into the extractor<br \/>\ncontainer&#8217;s filesystem containing the host CRI-O socket.<\/p>\n<p>## Affected Code<\/p>\n<p>### 1. Insufficient privilege drop (Rust \u2014 extractor coordinator)<\/p>\n<p>**File:** `extractor\/src\/insights_runtime_extractor.rs`<\/p>\n<p>&#8220;`rust<br \/>\n\/\/ Lines 139-146 \u2014 seteuid-only drop, guard skipped for root containers<br \/>\njoin_process_namespaces(process.pid)?;<br \/>\nchange_dir(current_dir);<br \/>\nswitch_user(*process.uid)?;<br \/>\nif *process.uid != 0 {<br \/>\n    perms::check_no_privileged_perms()<br \/>\n        .expect(&#8220;Must not have privileged permissions to run fingerprints&#8221;);<br \/>\n}<br \/>\nfingerprint::run_fingerprints(&amp;config, out_dir, &amp;process);<br \/>\n&#8220;`<\/p>\n<p>&#8220;`rust<br \/>\n\/\/ Lines 182-185 \u2014 only effective UID changed; ruid\/suid stay 0<br \/>\nfn switch_user(uid: u32) -&gt; Result {<br \/>\n    debug!(&#8220;&#8230; Becoming user: {uid}&#8221;);<br \/>\n    seteuid(uid.into()).map_err(|e| ScannerError::Errno(e))<br \/>\n}<br \/>\n&#8220;`<\/p>\n<p>### 2. Execution of untrusted binary (Go \u2014 fingerprint)<\/p>\n<p>**File:** `fingerprints\/pkg\/utils\/file.go`<\/p>\n<p>&#8220;`go<br \/>\n\/\/ Lines 75-80 \u2014 executes a path taken verbatim from workload&#8217;s argv[0]<br \/>\nfunc GetExecutableVersionOutput(executable string) (string, error) {<br \/>\n    out, err := exec.Command(executable, &#8220;&#8211;version&#8221;).Output()<br \/>\n    if err != nil {<br \/>\n        return &#8220;&#8221;, err<br \/>\n    }<br \/>\n    return string(out), nil<br \/>\n}<br \/>\n&#8220;`<\/p>\n<p>### 3. Workload-controlled path forwarded (Rust \u2014 version_executable)<\/p>\n<p>**File:** `version_executable.rs`<\/p>\n<p>&#8220;`rust<br \/>\n\/\/ Lines 29-34 \u2014 workload-controlled command_line[0] forwarded to fingerprint<br \/>\nreturn Some(vec![<br \/>\n    fpr_kind_executable,<br \/>\n    out_dir.to_string(),<br \/>\n    String::from(&amp;process.command_line[0]),<br \/>\n    String::from(&amp;version_executable.runtime_kind_name),<br \/>\n]);<br \/>\n&#8220;`<\/p>\n<p>## Attack Pattern<\/p>\n<p>**Attacker:** Any tenant able to schedule a pod (unprivileged, any namespace)<br \/>\n**Victim:** The node running the insights-runtime-extractor DaemonSet<br \/>\n**Trigger:** Automatic \u2014 the DaemonSet scans all container processes on the node<\/p>\n<p>**Attack sequence:**<\/p>\n<p>1. Attacker creates a pod whose process name matches a configured<br \/>\n   versioned-executable pattern (`node`, `python`, `python3`, `MainThread`,<br \/>\n   or contains `java`)<br \/>\n2. The pod&#8217;s main binary (at the path matching argv[0]) is a malicious<br \/>\n   executable that calls `setuid(0)` to restore root<br \/>\n3. When the insights operator triggers a scan, the DaemonSet forks, enters the<br \/>\n   attacker&#8217;s mount namespace, and executes the attacker&#8217;s binary with ruid=0<br \/>\n4. The attacker&#8217;s code regains full root with `CAP_SYS_ADMIN` in the host user<br \/>\n   namespace<br \/>\n5. The inherited cwd contains the host CRI-O socket \u2192 full node compromise<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The insights-runtime-extractor runs as a privileged DaemonSet (`hostPID: true`)<br \/>\nthat scans container processes for runtime fingerprinting. When scanning a<br \/>\ncontainer, the coordinator:<\/p>\n<p>1. **fork()s** a<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-39014","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/39014","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=39014"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=39014"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=39014"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}