Fedora Account System
Red Hat Associate
Red Hat Customer
AI_ONLY_REPORT package: cockpit-machines-348-1.el10 ------ Summary: Sensitive Data Exposure in Process List via JSON Argument in install_machine.py: VM installation credentials are passed in a JSON command-line argument, which can expose `rootPassword` and `userPassword` through local process inspection on affected host configurations. Requirements to exploit: Local access to the host running `cockpit-machines`, the ability to inspect another running process's command line, and a VM create/install operation that supplies `rootPassword` and/or `userPassword` while `install_machine.py` is still running. Exploitability depends on host process-visibility settings and timing. Component affected: `cockpit-machines` create/install flow in `src/libvirtApi/domain.ts` (`domainCreate`, `domainInstall`) and `src/scripts/install_machine.py` Version affected: `cockpit-machines-348-1.el10` Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N - 4.7 (MEDIUM) AV:L - The issue is exploitable from the local host by inspecting process arguments. AC:L - Once the affected process is running, reading `ps` output or `/proc/<pid>/cmdline` is straightforward where host policy permits it. PR:L - The attacker needs local access sufficient to observe the process on the host. UI:R - Credential exposure occurs only when a user triggers the affected VM create/install flow with password fields populated. S:U - The issue does not cross a security boundary within the product. C:H - The exposed data can include guest login credentials, including `rootPassword` and `userPassword`, or other directly reusable credential material in some paths. I:N - This issue does not directly modify data. A:N - This issue does not directly affect service availability. Impact: Moderate. This is a confidentiality issue that can disclose guest credentials, but it requires local host access, depends on process-visibility policy, and is only exposed while the affected create/install workflow is active. That is consistent with a flaw that can lead to compromise under specific circumstances, but is not an easy remote or unauthenticated system-compromise condition. Embargo: no Reason: The issue appears to require local access and runtime timing, with mitigation available through a relatively contained code change and host process-visibility hardening. This is better handled through normal coordinated remediation than embargoed treatment. Acknowledgement: Aisle Research Vulnerability Details: The VM create/install path passes a full JSON payload to `install_machine.py` through `argv`, and that payload includes credential fields. The Python side then deserializes the JSON directly from the first positional argument: ```python args = json.loads(sys.argv[1], strict=False) ``` The affected create and install flows build JSON that includes `rootPassword` and `userPassword`, then invoke `install_machine.py` with that JSON as a command-line argument. This makes the credentials observable through process metadata on hosts where other local users can inspect command lines. The exposure window can be meaningful because the install path may remain active for an extended period during guest installation. Steps to reproduce: 1. Start a VM creation or installation through the affected workflow with `rootPassword` and/or `userPassword` set. 2. While `install_machine.py` is still running, identify the process on the same host: `ps -ef | grep install_machine.py` 3. Read the command line for the matching process: `tr '\0' ' ' < /proc/<pid>/cmdline` 4. Observe that the JSON argument contains `rootPassword` and/or `userPassword` in cleartext, or other directly reusable credential material in some cloud-image paths. If host policy restricts cross-process inspection, the disclosure may not be observable from a separate local account, but the underlying behavior still places secrets in `argv`. Mitigation: Avoid passing secrets in process arguments. Until code is corrected, reduce exposure by restricting process inspection on the host where possible and by avoiding use of password-bearing install flows when another provisioning method is available. Hardening `/proc` visibility can reduce exploitability, but it does not remove the underlying secret-in-`argv` issue. Proposed Fix: Read the JSON payload from standard input, keep an `argv` fallback only for compatibility, and update both call sites to write the payload via `Spawn.input()` instead of passing it in the command line. ```diff diff --git a/src/scripts/install_machine.py b/src/scripts/install_machine.py index 0000000..1111111 100755 — a/src/scripts/install_machine.py +++ b/src/scripts/install_machine.py @@ -313,9 +313,16 @@ def inject_metadata(xml): logging.basicConfig(level=logging.ERROR, format='%(message)s') -logging.debug(sys.argv[1]) - -args = json.loads(sys.argv[1], strict=False) +payload = None +if len(sys.argv) > 1 and sys.argv[1]: + # backward compatibility: prefer stdin, accept argv for older callers + payload = sys.argv[1] +else: + payload = sys.stdin.read() + +if not payload: + raise ValueError("missing install_machine payload") + +args = json.loads(payload, strict=False) logging.debug(args) diff --git a/src/libvirtApi/domain.ts b/src/libvirtApi/domain.ts index 2222222..3333333 100644 — a/src/libvirtApi/domain.ts +++ b/src/libvirtApi/domain.ts @@ -591,12 +591,13 @@ export async function domainCreate(...) { await hashPasswords(args); await python.spawn( + const p = python.spawn( installVmScript, [JSON.stringify(args)], + [], { err: "message", environ: ['LC_ALL=C.UTF-8'], ...(connectionName === "system" ? { superuser: "try" } : { }) }); + p.input(JSON.stringify(args)); + await p; @@ -1022,13 +1023,14 @@ export async function domainInstall({ vm } : { vm: VM }): Promise<string> { return python.spawn( + const p = python.spawn( installVmScript, [args], + [], { err: "message", environ: ['LC_ALL=C.UTF-8'], ...(vm.connectionName === "system" ? { superuser: "try" } : { }) }) .catch(ex => { + }); + p.input(args); + return p.catch(ex => { console.error(JSON.stringify(ex)); return Promise.reject(ex); }) ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use