CVE-2026-112941
filelock: SoftReadWriteLock follows a lock tree swapped in after its first acquire and writes lock records into directories of the user running the lock
filelock is a platform-independent file lock for Python. From 4.1.0 until 4.2.1, SoftReadWriteLock and AsyncSoftReadWriteLock cache a successful check of the <path>.rw lock tree and resolve its names again during later record operations, allowing another local user who can replace that tree after the first acquisition to redirect lock-record writes into directories writable by the lock user. This issue is fixed in version 4.2.1.
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- Low
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
3.3
filelock: SoftReadWriteLock follows a lock tree swapped in after its first acquire and writes lock records into directories of the user running the lock
filelock is a platform-independent file lock for Python. From 4.1.0 until 4.2.1, SoftReadWriteLock and AsyncSoftReadWriteLock cache a successful check of the <path>.rw lock tree and resolve its names again during later record operations, allowing another local user who can replace that tree after the first acquisition to redirect lock-record writes into directories writable by the lock user. This issue is fixed in version 4.2.1.
- Record
CVE-2026-112941- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-367
- Updated
- 2026-11-02
EUVDEUVD-2026-105032
3.3
filelock is a platform-independent file lock for Python. From 4.1.0 until 4.2.1, SoftReadWriteLock and AsyncSoftReadWriteLock cache a successful check of the <path>.rw lock tree and resolve its names again during later record operations, allowing another local user who can replace that tree after the first acquisition to redirect lock-record writes into directories writable by the lock user. This issue is fixed in version 4.2.1.
- Record
EUVD-2026-105032- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-wfhq-q4j2-c37m
3.3
filelock: SoftReadWriteLock follows a lock tree swapped in after its first acquire and writes lock records into directories of the user running the lock
SoftReadWriteLock (and AsyncSoftReadWriteLock, which wraps one) checks once per lock object, by name, that <path>.rw, <path>.rw/gen and <path>.rw/holders are real directories and not symbolic links (files that redirect to another path). It then keeps only a boolean. Every later record operation resolves the full path again, and O_NOFOLLOW (a flag that makes an open fail when the final name is a symbolic link) protects the last component only. Another local user (the other user below) who can write the directory holding the lock, or who created <path>.rw first in a sticky directory such as /tmp (the sticky bit is a directory flag that lets only a file's owner rename or remove it), can put a tree under that name whose gen or holders is a symbolic link into a directory of the user running the lock (the lock user below).
A long-running process of the lock user that has already passed the check then creates, renames over and deletes files there with the lock user's privileges, including in 0700 directories the other user cannot open. The names and bytes are filelock's own lock records, not chosen by the other user. The scanner's reproducer replaces .git/HEAD in the lock user's private repository so that git status fails. There is no race. Affected versions: filelock >= 4.1.0 and <= 4.2.0. Anthropic's OSS Scanner reported it in private as ANT-2026-WXXRI4M4 [high, CWE-367], titled "SoftReadWriteLock follows gen dir swapped for a symlink after first acquire".
Severity
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N, 3.3 (Low).
AV:L (local): the other user needs an account on the same host. AC:L (low attack complexity): the swap happens between two acquisitions, with no race to win. PR:L (low privileges): a local user with ordinary privileges is enough. UI:N (no user interaction): the lock user's process acts on its own. C:N (no confidentiality impact): the other user learns nothing. I:L (low integrity impact): the lock user's process replaces a file named HEAD, creates epoch and generation records, and deletes files whose names match the protocol's patterns, in any directory the lock user can write, with the lock user's privileges. The other user does not choose the bytes, but the files are gone and the chosen directory (a git repository) stops working. A:N (no availability impact): the lock itself keeps working and the lock user's process does not stall. The scanner rated it high; we scored the vector for a lock user with ordinary privileges.
Classification from the external review: conditional security. It is a cross-user replacement of a cached .rw tree that redirects later writes of the lock user through an intermediate symbolic link. It needs a planted tree in sticky /tmp or a writable parent without the sticky bit. Scoring note: we rate integrity low rather than high. The bytes written through the swapped tree are filelock's own records, not content the other user chose, so the lower reading of the CVSS integrity metric applies.
Scope and preconditions
- Trust boundary: the other party is a different local account with write access to the lock's parent directory. Without the sticky bit (a
0777scratch or spool directory, or a group-writable project or cache directory shared with that account's group) write access alone is enough. The other user renames the lock user's own0700<path>.rwaside and puts its tree in place. In a sticky parent such as/tmpthe extra precondition is that it created<path>.rw(with realgenandholdersdirectories, mode0777) before the lock user's first acquire.prepare()accepts an existing tree whoever owns it, and the other user later replaces its owngenwith a symbolic link.fs.protected_symlinks=1(a Linux setting that refuses to follow another user's symbolic link in a world-writable sticky directory) does not intervene, because the link sits inside the other user's own non-sticky<path>.rw, not in the…
- Record
GHSA-wfhq-q4j2-c37m- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-367
- Updated
- 2026-11-02
NVD
3.3
filelock is a platform-independent file lock for Python. From 4.1.0 until 4.2.1, SoftReadWriteLock and AsyncSoftReadWriteLock cache a successful check of the <path>.rw lock tree and resolve its names again during later record operations, allowing another local user who can replace that tree after the first acquisition to redirect lock-record writes into directories writable by the lock user. This issue is fixed in version 4.2.1.
- Record
CVE-2026-112941- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-367
- Updated
- 2026-11-02
OSV
3.3
filelock: SoftReadWriteLock follows a lock tree swapped in after its first acquire and writes lock records into directories of the user running the lock
filelock is a platform-independent file lock for Python. From 4.1.0 until 4.2.1, SoftReadWriteLock and AsyncSoftReadWriteLock cache a successful check of the <path>.rw lock tree and resolve its names again during later record operations, allowing another local user who can replace that tree after the first acquisition to redirect lock-record writes into directories writable by the lock user. This issue is fixed in version 4.2.1.
- Record
CVE-2026-112941- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-367
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-112941
3.3
filelock is a platform-independent file lock for Python. From 4.1.0 until 4.2.1, SoftReadWriteLock and AsyncSoftReadWriteLock cache a successful check of the <path>.rw lock tree and resolve its names again during later record operations, allowing another local user who can replace that tree after the first acquisition to redirect lock-record writes into directories writable by the lock user. This issue is fixed in version 4.2.1.
- Record
DEBIAN-CVE-2026-112941- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Updated
- 2026-11-02
OSVGHSA-wfhq-q4j2-c37m
3.3
filelock: SoftReadWriteLock follows a lock tree swapped in after its first acquire and writes lock records into directories of the user running the lock
SoftReadWriteLock (and AsyncSoftReadWriteLock, which wraps one) checks once per lock object, by name, that <path>.rw, <path>.rw/gen and <path>.rw/holders are real directories and not symbolic links (files that redirect to another path). It then keeps only a boolean. Every later record operation resolves the full path again, and O_NOFOLLOW (a flag that makes an open fail when the final name is a symbolic link) protects the last component only. Another local user (the other user below) who can write the directory holding the lock, or who created <path>.rw first in a sticky directory such as /tmp (the sticky bit is a directory flag that lets only a file's owner rename or remove it), can put a tree under that name whose gen or holders is a symbolic link into a directory of the user running the lock (the lock user below).
A long-running process of the lock user that has already passed the check then creates, renames over and deletes files there with the lock user's privileges, including in 0700 directories the other user cannot open. The names and bytes are filelock's own lock records, not chosen by the other user. The scanner's reproducer replaces .git/HEAD in the lock user's private repository so that git status fails. There is no race. Affected versions: filelock >= 4.1.0 and <= 4.2.0. Anthropic's OSS Scanner reported it in private as ANT-2026-WXXRI4M4 [high, CWE-367], titled "SoftReadWriteLock follows gen dir swapped for a symlink after first acquire".
Severity
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N, 3.3 (Low).
AV:L (local): the other user needs an account on the same host. AC:L (low attack complexity): the swap happens between two acquisitions, with no race to win. PR:L (low privileges): a local user with ordinary privileges is enough. UI:N (no user interaction): the lock user's process acts on its own. C:N (no confidentiality impact): the other user learns nothing. I:L (low integrity impact): the lock user's process replaces a file named HEAD, creates epoch and generation records, and deletes files whose names match the protocol's patterns, in any directory the lock user can write, with the lock user's privileges. The other user does not choose the bytes, but the files are gone and the chosen directory (a git repository) stops working. A:N (no availability impact): the lock itself keeps working and the lock user's process does not stall. The scanner rated it high; we scored the vector for a lock user with ordinary privileges.
Classification from the external review: conditional security. It is a cross-user replacement of a cached .rw tree that redirects later writes of the lock user through an intermediate symbolic link. It needs a planted tree in sticky /tmp or a writable parent without the sticky bit. Scoring note: we rate integrity low rather than high. The bytes written through the swapped tree are filelock's own records, not content the other user chose, so the lower reading of the CVSS integrity metric applies.
Scope and preconditions
- Trust boundary: the other party is a different local account with write access to the lock's parent directory. Without the sticky bit (a
0777scratch or spool directory, or a group-writable project or cache directory shared with that account's group) write access alone is enough. The other user renames the lock user's own0700<path>.rwaside and puts its tree in place. In a sticky parent such as/tmpthe extra precondition is that it created<path>.rw(with realgenandholdersdirectories, mode0777) before the lock user's first acquire.prepare()accepts an existing tree whoever owns it, and the other user later replaces its owngenwith a symbolic link.fs.protected_symlinks=1(a Linux setting that refuses to follow another user's symbolic link in a world-writable sticky directory) does not intervene, because the link sits inside the other user's own non-sticky<path>.rw, not in the…
- Record
GHSA-wfhq-q4j2-c37m- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Weakness
- CWE-367
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-112941
3.3
filelock is a platform-independent file lock for Python. From 4.1.0 until 4.2.1, SoftReadWriteLock and AsyncSoftReadWriteLock cache a successful check of the <path>.rw lock tree and resolve its names again during later record operations, allowing another local user who can replace that tree after the first acquisition to redirect lock-record writes into directories writable by the lock user. This issue is fixed in version 4.2.1.
- Record
UBUNTU-CVE-2026-112941- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
filelockPyPI |
4.1.0 to 4.2.0 | 4.2.1 |
python-filelockDebian:12 |
All versions, plus listed versions 3.12.2-13.12.3-13.12.4-13.13.1-13.13.3-1 Show 29 moreShow less3.13.4-13.14.0-13.15.4-13.16.1-13.16.1-23.17.0-13.18.0-13.19.1-13.20.0-13.20.2-13.20.3-13.24.3-13.25.0-13.25.2-13.29.0-13.29.4-13.29.5-13.29.7-13.32.0-13.32.2-13.32.4-13.32.4-23.32.5-13.32.6-13.9.0-13.9.0-1+deb12u14.0.1-14.0.12-14.1.1-1 |
None known |
python-filelockDebian:13 |
All versions, plus listed versions 3.18.0-13.18.0-1+deb13u13.19.1-13.20.0-13.20.2-1 Show 17 moreShow less3.20.3-13.24.3-13.25.0-13.25.2-13.29.0-13.29.4-13.29.5-13.29.7-13.32.0-13.32.2-13.32.4-13.32.4-23.32.5-13.32.6-14.0.1-14.0.12-14.1.1-1 |
None known |
python-filelockDebian:14 |
All versions, plus listed versions 3.18.0-13.19.1-13.20.0-13.20.2-13.20.3-1 Show 16 moreShow less3.24.3-13.25.0-13.25.2-13.29.0-13.29.4-13.29.5-13.29.7-13.32.0-13.32.2-13.32.4-13.32.4-23.32.5-13.32.6-14.0.1-14.0.12-14.1.1-1 |
None known |
filelockPyPI |
4.1.0 up to 4.2.1, plus listed versions 4.1.14.1.24.2.0 |
4.2.1 |
python-filelockUbuntu:Pro:18.04:LTS |
All versions, plus listed versions 2.0.11-12.0.12-12.0.13-13.0.0-23.0.3-13.0.4-13.0.4-1ubuntu0.1~esm1 |
None known |
python-filelockUbuntu:Pro:20.04:LTS |
All versions, plus listed versions 3.0.12-13.0.12-23.0.12-2ubuntu0.1~esm1 |
None known |
python-filelockUbuntu:Pro:22.04:LTS |
All versions, plus listed versions 3.0.12-23.3.2-13.4.0-13.4.2-13.4.2-23.6.0-13.6.0-1ubuntu0.1~esm1 |
None known |
python-filelockUbuntu:Pro:24.04:LTS |
All versions, plus listed versions 3.12.2-13.12.4-13.13.1-13.13.1-1ubuntu0.1~esm1 |
None known |
python-filelockUbuntu:26.10 |
All versions, plus listed versions 3.20.3-13.29.4-13.32.0-13.32.2-1 |
None known |
python-filelockUbuntu:26.04:LTS |
All versions, plus listed versions 3.18.0-13.20.0-13.20.2-13.20.3-1 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-112941 is a low vulnerability (CVSS 3.3) in Tox-dev Filelock, published October 20, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.13%, the 2nd percentile. Fixed in filelock 4.2.1.
References
github.com/tox-dev/filelock/security/advisories/GHSA-wfhq-q4j2-c37m
github.com/tox-dev/filelock/pull/842
github.com/tox-dev/filelock/commit/bfa066d65a1ba9106f86ee9d027f7588b9c77e03
github.com/tox-dev/filelock/releases/tag/4.2.1
nvd.nist.gov/vuln/detail/CVE-2026-112941
github.com/advisories/GHSA-wfhq-q4j2-c37m
Left out here: the rest of 2 source descriptions. The JSON record has them.