Skip to main content
Vulnerability Database/CVE-2026-112934

CVE-2026-112934: Tox-dev Filelock Privilege Escalation

CVE-2026-112934 is a privilege escalation vulnerability in Tox-dev Filelock allowing local users to manipulate lock directories and cause unauthorized file writes. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-112934 Overview

CVE-2026-112934 affects filelock, a platform-independent file lock library for Python maintained by tox-dev. The vulnerability resides in SoftReadWriteLock, which refreshes holder records by name rather than through a protected descriptor. A local user with rename access to the lock directory can swap a holder record for a named pipe (FIFO) and stall the lock holder, or exploit a permissive hard-link policy to redirect writes to an attacker-chosen target file. Versions 4.0.0 through 4.2.0 are affected, and the issue is fixed in 4.2.1. The weakness is classified under [CWE-62: UNIX Symbolic Link (Symlink) Following].

Critical Impact

A local user with write access to the lock directory can hang processes relying on SoftReadWriteLock or cause them to write through attacker-controlled links, enabling denial of service and limited integrity loss.

Affected Products

  • tox-dev filelock versions 4.0.0 through 4.2.0
  • Python applications using filelock.SoftReadWriteLock
  • Downstream packages bundling vulnerable filelock releases

Discovery Timeline

  • 2026-10-20 - CVE-2026-112934 published to the National Vulnerability Database (NVD)
  • 2026-10-22 - Last updated in NVD database

Technical Details for CVE-2026-112934

Vulnerability Analysis

SoftReadWriteLock coordinates readers and writers by writing holder records inside a <path>.rw directory and refreshing them through a periodic heartbeat. In the affected releases, the heartbeat and ownership checks resolve those records by path name instead of through a descriptor opened with symlink-following disabled. A local attacker who can rename or create entries in the coordination directory can therefore substitute a holder record with a FIFO or a hard link to an unrelated file.

When the heartbeat opens the substituted FIFO, it blocks waiting for a reader that never arrives, stalling the lock holder and any process waiting on the lock. If the host policy permits unprivileged hard links to files the lock user can write, the heartbeat writes the refreshed record into the linked target, corrupting that file. The result is a local denial of service with a limited integrity impact against the lock user's writable files.

Root Cause

The root cause is unsafe path resolution during holder record refresh. SoftReadWriteLock reopened <path>.rw, gen, and holders by name on every heartbeat without validating that the opened inode was the one it originally created. This allowed a swapped tree, a symlink, a Windows junction, or a FIFO at the record name to redirect or stall I/O performed by the lock process.

Attack Vector

Exploitation requires a local account with rename or write access inside the lock directory. The attacker does not need elevated privileges, no user interaction is required, and the attack is purely local. The adversary either places a FIFO at a holder record path to stall the heartbeat, or links a reachable file so the heartbeat's writes land in the attacker-chosen target.

text
# Patch excerpt from docs/changelog/842.bugfix.rst
:class:`~filelock.SoftReadWriteLock` reaches its records through descriptors of ``<path>.rw`` and ``gen`` or ``holders``
opened without following symlinks. On Windows it holds those directories open and refuses a junction (a directory that
points at another directory). A tree swapped in after an earlier acquire therefore cannot redirect them. Its heartbeat
rewrites a holder record only when the name still leads to the file it created, and does not block on a FIFO (a named
pipe). A heartbeat that finds ``<path>.rw`` replaced by a symlink or junction reports the hold lost instead of ending
the heartbeat thread. A live lock object repeats the ownership check whenever the tree it opens is not the one it
prepared.

Source: GitHub Commit bfa066d

Detection Methods for CVE-2026-112934

Indicators of Compromise

  • Presence of FIFO or symlink nodes inside a <path>.rw, gen, or holders directory used by filelock
  • Python processes blocked in open() or write() calls targeting filelock holder records
  • Unexpected modifications to files owned by the lock user that correspond in timing to lock heartbeats
  • Lock coordination directories owned by a user other than the application identity

Detection Strategies

  • Inventory Python environments and identify installations of tox-dev/filelock with versions between 4.0.0 and 4.2.0 using pip list or SBOM tooling
  • Audit filesystem permissions on directories passed to SoftReadWriteLock, flagging world-writable or shared parents such as /tmp
  • Monitor for creation of non-regular files (FIFOs, symlinks, junctions) inside filelock coordination directories using Linux audit rules or Windows file system auditing

Monitoring Recommendations

  • Enable auditd watches on application lock directories with rules such as -w /path/to/lockdir -p wa -k filelock_tamper
  • Alert on long-running Python threads blocked on I/O to paths matching *.rw/holders/* patterns
  • Correlate heartbeat stalls with concurrent rename or link events in the same directory to identify active abuse attempts

How to Mitigate CVE-2026-112934

Immediate Actions Required

  • Upgrade filelock to version 4.2.1 or later across all Python environments: pip install --upgrade 'filelock>=4.2.1'
  • Relocate SoftReadWriteLock coordination directories out of world-writable paths such as /tmp and into application-private directories
  • Remove any stale <path>.rw or claims directories owned by accounts other than the application identity before restarting services

Patch Information

The fix is included in filelock 4.2.1 through pull request #842 and commit bfa066d. The patch opens <path>.rw, gen, and holders without following symlinks, holds the directories open on Windows to refuse junctions, verifies that holder record names still resolve to the inode the lock created, and refuses to block on FIFOs. Full technical details are in the GitHub Security Advisory GHSA-fj95-fr6c-h845.

Workarounds

  • Restrict the parent of the lock directory to the application user with chmod 700 and apply the sticky bit on shared parents
  • Disable or restrict unprivileged hard links on Linux by setting sysctl fs.protected_hardlinks=1 and fs.protected_symlinks=1
  • Avoid SoftReadWriteLock on multi-tenant hosts until the upgrade is deployed, substituting an OS-level lock where feasible
bash
# Harden the host and upgrade filelock
sudo sysctl -w fs.protected_hardlinks=1
sudo sysctl -w fs.protected_symlinks=1

# Pin a safe filelock version in requirements
echo 'filelock>=4.2.1' >> requirements.txt
pip install --upgrade -r requirements.txt

# Secure the lock directory
install -d -m 0700 -o appuser -g appuser /var/lib/myapp/locks

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.