Bug 2569357 (CVE-2026-125672)

Summary: CVE-2026-125672 cockpit: cockpit-storaged: Tang keyserver address from an untrusted LUKS header clevis token reaches curl's argument vector as an option
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: rhel-process-autobot, watson-tool-maintainers
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in cockpit-storaged. A Tang keyserver address read from a clevis token in a LUKS header is concatenated into curl's argument vector without a "--" separator. An address beginning with "-" is parsed by curl as an option instead of a hostname, allowing an attacker who can attach a crafted LUKS/clevis block device (for example, a local unprivileged user with an active console or desktop login session) to have an administratively-privileged Cockpit user unknowingly trigger curl option injection when editing the device's Tang keyserver settings. This can lead to arbitrary file read or write as the Cockpit session user.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-11-10 09:19:22 UTC
A flaw was found in cockpit. The cockpit-storaged module's get_tang_adv() function (pkg/storaged/crypto/tang.jsx) builds curl's argument vector by string concatenation: cockpit.spawn(["curl", "-sSf", url + "/adv"]), with no "--" separator between options and the positional argument. On the Edit-Tang-keyserver path, this url value is read verbatim from a clevis token embedded in the LUKS header of a block device, which is data controlled by whoever can write to or attach that device, not necessarily the Cockpit operator. validate_url() only rejects empty strings and values that fail JavaScript URL parsing; a value such as "-K/var/tmp/stash" parses successfully (hostname "-k") and is accepted. When such a value reaches curl, curl interprets it as the "-K" (config file) option instead of a hostname, loading an attacker-planted curl configuration file. The planted configuration can set "output" to any path the Cockpit session user can write, "url" to a file:// URL to read any file that user can read, or "upload-file" with a remote destination to exfiltrate data -- all running as the Cockpit session user (not root; the LUKS-header read itself runs with superuser privileges via python.spawn(..., {superuser: "require"}), but the subsequent curl invocation does not). A local unprivileged user with a local, active console or desktop login session (not a remote SSH or Cockpit web session) can plant the malicious LUKS header using the standard, default-granted udisks2 org.freedesktop.udisks2.loop-setup polkit permission (allow_active=yes), requiring no elevated privilege. An administrator with Cockpit access who then opens the "Edit Tang keyserver" dialog for that device and clicks Save, without recognizing the prefilled value as a curl option rather than an address, triggers the chain. No non-default configuration is required.