Bug 2466442 (CVE-2026-91205) - CVE-2026-91205 cockpit-files: cockpit-files: Local attacker can hijack file ownership via symlink race
Summary: CVE-2026-91205 cockpit-files: cockpit-files: Local attacker can hijack file o...
Keywords:
Status: NEW
Alias: CVE-2026-91205
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On: 2537070
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-04 18:07 UTC by OSIDB Bzimport
Modified: 2026-09-18 19:15 UTC (History)
3 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-05-04 18:07:40 UTC
AI_ONLY_REPORT
package: cockpit-files-36-1.el10
------
Summary: Symlink Hijacking in chown during directory creation: a local  
attacker who controls a writable parent directory can race privileged  
`mkdir` and `chown` operations and redirect the ownership change to a  
symlink target.
Requirements to exploit: A local unprivileged attacker must control the  
parent directory of the path being created, that directory must be writable  
in a way that allows entry replacement, a user must perform the directory  
creation through Cockpit Files with owner assignment enabled, and the  
attacker must win the race between `mkdir` and `chown`.
Component affected: `cockpit-files-36-1.el10`, `src/dialogs/mkdir.tsx`,  
`create_directory()`
Version affected: `cockpit-files-36-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:H/PR:L/UI:R/S:U/C:H/I:H/A:N - 6.0 (MEDIUM)
AV:L - The attacker needs local access to a system where Cockpit Files  
is used.
AC:H - Exploitation depends on winning a narrow pathname race and on an  
attacker-controlled writable parent directory.
PR:L - The attacker needs only a low-privileged local account to prepare  
the directory and run the race.
UI:R - A user must trigger the vulnerable directory creation flow.
S:U - The impact remains within the same security scope.
C:H - A successful attack can redirect ownership changes onto sensitive  
files and expose their contents.
I:H - A successful attack can grant write control over files whose  
ownership should not be attacker-controlled.
A:N - The demonstrated impact is confidentiality and integrity  
compromise rather than a direct denial of service.
Impact: Moderate. The flaw can compromise confidentiality and integrity,  
but exploitation is materially constrained by local access, required user  
interaction, a race condition, and a specific writable-parent-directory  
setup. That aligns more closely with Red Hat's Moderate category than  
Important.
Embargo: no
Reason: The issue is local, requires a privileged user action and  
favorable filesystem conditions, and has straightforward operational  
mitigations, so delayed public disclosure is not strongly justified on the  
available evidence.
Acknowledgement: Aisle Research
Vulnerability Details: In the privileged owner-assignment path, directory  
creation and ownership change are performed as two separate operations on  
the same pathname:
```ts
async function create_directory(path: string, owner?: string) {
if (owner !== undefined) {
const opts = { err: "message", superuser: "require" } as const;
await cockpit.spawn(["mkdir", path], opts);
await cockpit.spawn(["chown", owner, path], opts);
} else {
await cockpit.spawn(["mkdir", path], { err: "message" });
}
}
```
If an attacker can modify the parent directory contents between these two  
calls, the newly created directory entry can be replaced with a symlink  
before `chown` runs. In that situation, the ownership change may be applied  
to the symlink target rather than the directory that Cockpit Files intended  
to create. The risk is limited to scenarios where the attacker can control  
the parent directory and where the superuser-assisted owner-setting path is  
actually used.
Steps to reproduce:
1. Prepare two users: an unprivileged local `attacker` account and a user  
who will operate Cockpit Files with superuser access.
2. Create an attacker-controlled parent directory, for example:
`sudo mkdir -p /home/attacker/share`
`sudo chown attacker:attacker /home/attacker/share`
`sudo chmod 0777 /home/attacker/share`
3. As the attacker, run a loop that continually replaces the target name  
with a symlink:
`while true; do rm -rf /home/attacker/share/poc; ln -s /etc/shadow  
/home/attacker/share/poc 2>/dev/null; done`
4. In Cockpit Files, browse to `/home/attacker/share/`, choose to create  
directory `poc`, and use the owner-setting flow that triggers the  
privileged `chown` path.
5. If the race is won, verify whether the ownership of `/etc/shadow`  
changed unexpectedly:
`ls -l /etc/shadow`
Mitigation: Avoid using the privileged owner-setting directory creation  
flow inside attacker-writable directories. Restrict write access on shared  
parent directories, use sticky-bit protections where appropriate, and  
prefer symlink-safe ownership changes that do not dereference  
attacker-controlled path replacements.
Proposed Fix: Add `--no-dereference` to the privileged `chown` invocation  
so that ownership changes do not follow a substituted symlink.
```diff
diff --git a/src/dialogs/mkdir.tsx b/src/dialogs/mkdir.tsx
@@ -42,7 +42,7 @@ async function create_directory(path: string, owner?:  
string) {
if (owner !== undefined) {
const opts = { err: "message", superuser: "require" } as const;
await cockpit.spawn(["mkdir", path], opts);
       await cockpit.spawn(["chown", owner, path], opts);
+        await cockpit.spawn(["chown", "--no-dereference", owner, path],  
opts);
      } else {
          await cockpit.spawn(["mkdir", path], { err: "message" });
      }
```


------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.