KEVWire

Security intelligence, with context.

Response snapshot Oct 29, 2026, 03:36 UTC

Back to the wire
Permalink
VulnerabilityCVE-2026-112938

filelock: StrictSoftFileLock follows a symbolic link swapped in at <path>.filelock and creates claim files in a directory another local user chooses

StrictSoftFileLock and AsyncStrictSoftFileLock check .filelock (the coordination directory that holds the lock's state) with one lstat call on its name. lstat reports what a name is without following a symbolic link (a file that redirects to another path). After that check, the code reaches .

At a glance

Exploited
Not known
Severity
5.8 Medium (CVSS 3.1)
Chance of exploitation
Not estimated
Sources
1 source

What to do

GitHub lists first patched versions: filelock: 4.2.1. Confirm the affected range and upgrade guidance in the exact advisory.

Read GitHub-reviewed advisory GHSA-m462-7rxw-wvpg (opens a new tab)

What happened

StrictSoftFileLock and AsyncStrictSoftFileLock check .filelock (the coordination directory that holds the lock's state) with one lstat call on its name. lstat reports what a name is without following a symbolic link (a file that redirects to another path). After that check, the code reaches .filelock/claims by pathname for every later operation (mkdir, scan, publish, link, unlink).

_open_directory passes O_NOFOLLOW (a flag that makes an open fail when the final name is a symbolic link), but the flag covers only the final claims component. The kernel follows a symbolic link in any earlier component.

Another local user (the other user below) who can rename .filelock exchanges it for a symbolic link after the check. In a shared directory without the sticky bit (a directory flag that lets only a file's owner rename or remove it), any user with write access can do this. Where the shared directory is sticky, such as /tmp, only the user who created .

filelock before the user running the lock (the lock user below) first used it can. The lock user's process (root's, if root takes the lock) then creates a claims directory and claim files (the files whose presence says a process wants or holds the lock) inside a directory the other user chooses but only the lock user can write.

Continue reading

When the link points at another strict lock's .filelock directory, the stranded claims make that lock time out for every process until an operator finds and force-breaks each one. The claims property and force_break() resolve the same path with no check at all. Affected versions: filelock >= 3.30.0 and .filelock first. PR:L (low privileges): an unprivileged account is enough. UI:N` (no user interaction): the lock user's process acts on its own.

C:L (low confidentiality impact): through claims, one file name per planted link from a directory only the lock user can list. I:L (low integrity impact): a directory named claims and files with filelock's fixed claim names and contents appear, created with the lock user's privileges, in a directory the other user chooses but cannot write. The process overwrites or truncates nothing that exists.

A:H (high availability impact): aimed at another strict lock of the lock user, the stranded claims deny that lock to every process until an operator finds and force-breaks each one. Classification from the review: security, conditional on the other user being able to rename the intermediate component. The scanner rated it high (CWE-363).

Scope and preconditions

- The other user can rename .filelock. In a writable directory without the sticky bit (a 0777 or group-writable project or cache directory), any user with write permission on the directory can, even though the lock user created and owns .filelock. In a sticky directory such as /tmp, only the user who created .

filelock before the lock user's first use can, because that user then owns both the directory and the symbolic link (the planting precondition of GHSA-9c4x-gm8v-wgc4). - The link's target is a directory the lock user can write. The effect that matters is on that directory. An acquire that completes through the link also holds the shared lock with its claims elsewhere, but a user who can rename .

filelock can defeat that lock's exclusion anyway. - fs.protected_symlinks=1 (a Linux setting that refuses to follow another user's symbolic link in a world-writable sticky directory) does not interfere. The link is an intermediate path component, not the last one. In the sticky-directory case it also sits in a directory the other user owns.

- Missed attempts show up to the lock user as SoftFileLockProtocolError or FileNotFoundError. The swap therefore works against a lock that a program takes more than once: a periodic job, a worker pool, or a caller that retries or waits with a timeout (each poll of a waiting acquisition is a new attempt).

- The two entry points that need no race (claims and force_break() on a resting symbolic link) depend on the lock user inspecting or recovering the lock. The planted link invites this by making acquire() fail with a protocol error. The force_break() variant works only when the lock user breaks claims that name a live process on its own host without checking them first, as the recovery loop in docs/tutorials.

rst does. docs/how-to.rst tells the operator to verify that the named owner is gone before breaking. - Platform: POSIX, demonstrated on Linux (tmpfs and overlayfs). Windows has no dir_fd (file operations relative to an open directory handle), and on Windows the documented requirement is a lock directory that untrusted users cannot write.

filelock's checks against another local user hold only when no other user can replace the lock's directory or any of its ancestors. That is the case when each ancestor belongs to the lock user or root and is either not writable by others or sticky. A user who can rename entries in a non-sticky directory above the lock controls every name below it. No file-based lock can defend against that.

Affected code

At the scanned commit b831496, the check and the first use are adjacent lines of [StrictSoftFileLock._acquire](https://github.com/tox-dev/filelock/blob/b831496b0273ecd11bf02b8d080ca8b673a538c1/src/filelock/_strict.py#L123-L128). There, [_ensure_protocol_directory](https://github.com/tox-dev/filelock/blob/b831496b0273ecd11bf02b8d080ca8b673a538c1/src/filelock/_strict.py#L996-L1006) runs lstat on .

filelock and then mkdir on .filelock/claims. [_open_directory](https://github.com/tox-dev/filelock/blob/b831496b0273ecd11bf02b8d080ca8b673a538c1/src/filelock/_strict.py#L950-L954) passes O_DIRECTORY | O_NOFOLLOW but receives the full .filelock/claims. The claim scan goes by pathname in [_read_existing_claims](https://github.com/tox-dev/filelock/blob/b831496b0273ecd11bf02b8d080ca8b673a538c1/src/filelock/_strict.

py#L509-L514) (directory.exists()) and [`_lis

Affected package ranges reported by GitHub: filelock: >= 3.30.0, <= 4.2.0

Scores and how they were measured

CVSS base severity

5.8

Version 3.1As of

CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:H

Measurement source (opens a new tab)

How bad it is if exploited. Not a prediction of exploitation or proof you are exposed.

EPSS probability

Not available

A model's estimate of exploitation in the next 30 days, not certainty or your own risk.

Related technology

Sources

  1. Primary source

    GitHub-reviewed advisory GHSA-m462-7rxw-wvpg (opens a new tab)

    The public advisory supplies the description, affected package/version ranges, and any listed CVSS metric. GitHub review is not local review.

    Published Checked

  2. Primary source

    GitHub public advisory API page (opens a new tab)

    The API page supplied GHSA-m462-7rxw-wvpg, its actual identifiers, source dates, and structured metrics.

    Published Date not suppliedChecked

Cite this record

For factual claims, cite the primary sources above; cite KEVWire for its compilation, dates, and classifications.

APA

KEVWire. (2026, October 28). filelock: StrictSoftFileLock follows a symbolic link swapped in at <path>.filelock and creates claim files in a directory another local user chooses (CVE-2026-112938). https://kevwire.com/record/CVE-2026-112938

MLA

"filelock: StrictSoftFileLock follows a symbolic link swapped in at <path>.filelock and creates claim files in a directory another local user chooses (CVE-2026-112938)." KEVWire, 28 Oct. 2026, kevwire.com/record/CVE-2026-112938.

Chicago

KEVWire. "filelock: StrictSoftFileLock follows a symbolic link swapped in at <path>.filelock and creates claim files in a directory another local user chooses (CVE-2026-112938)." Last modified October 28, 2026. https://kevwire.com/record/CVE-2026-112938.

Evidence summary (plain text)

filelock: StrictSoftFileLock follows a symbolic link swapped in at <path>.filelock and creates claim files in a directory another local user chooses (Oct 28, 2026).
StrictSoftFileLock and AsyncStrictSoftFileLock check  .filelock (the coordination directory that holds the lock's state) with one lstat call on its name. lstat reports what a name is without following a symbolic link (a file that redirects to another path). After that check, the code reaches  .filelock/claims by pathname for every later operation (mkdir, scan, publish, link, unlink). _open_directory passes O_NOFOLLOW (a flag that makes an open fail when the final name is a symbolic link), but the flag covers only the final claims component.
CVSS 5.8 (version 3.1; evidence as of Oct 28, 2026; https://github.com/advisories/GHSA-m462-7rxw-wvpg).
Sources:
GitHub-reviewed advisory GHSA-m462-7rxw-wvpg: https://github.com/advisories/GHSA-m462-7rxw-wvpg
GitHub public advisory API page: https://api.github.com/advisories?type=reviewed&per_page=100&sort=updated&direction=desc
Record ID: CVE-2026-112938.
Record origin: Ingested record.
AI evidence: Not assessed.
Known exploitation: Not assessed.
Zero-day status: Not assessed. KEV membership alone does not establish zero-day status.
About this data

This record was ingested from a data source. Retrieved: Oct 29, 2026, 03:20 UTC. Ingestion is not an independent editorial investigation.

A CISA KEV listing documents known exploitation, not necessarily a zero-day; absence from the catalog does not prove a vulnerability has never been exploited.

Technology tags indicate possible relevance, not verified exposure. Confirm the affected product, version, and configuration against your own inventory; KEVWire does not scan your systems.

A personal reading checklist on this device, not verified remediation.

Record JSON

Your account

Email alerts

Email alerts are coming as part of KEVWire Premium: join the waitlist. To follow your stack today, use its RSS feed, which honors your filters, or connect an AI agent through the API.

Suggest an improvement

Ideas, missing sources, corrections, and bugs are all welcome. No account needed. Suggestions are reviewed by a person before anything changes.

Record details

Record detail