VYPR
Moderate severityOSV Advisory· Published Jan 10, 2026· Updated Jan 12, 2026

filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock

CVE-2026-22701

Description

filelock is a platform-independent file lock for Python. Prior to version 3.20.3, a TOCTOU race condition vulnerability exists in the SoftFileLock implementation of the filelock package. An attacker with local filesystem access and permission to create symlinks can exploit a race condition between the permission validation and file creation to cause lock operations to fail or behave unexpectedly. The vulnerability occurs in the _acquire() method between raise_on_not_writable_file() (permission check) and os.open() (file creation). During this race window, an attacker can create a symlink at the lock file path, potentially causing the lock to operate on an unintended target file or leading to denial of service. This issue has been patched in version 3.20.3.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
filelockPyPI
< 3.20.33.20.3

Affected products

1

Patches

2
41b42dd2c72a

Fix TOCTOU symlink vulnerability in SoftFileLock (#465)

https://github.com/tox-dev/filelockBernát GáborJan 9, 2026via ghsa
2 files changed · +19 1
  • docs/index.rst+16 0 modified
    @@ -216,6 +216,22 @@ The :class:`SoftFileLock <filelock.SoftFileLock>` only watches the existence of
     portable, but also more prone to dead locks if the application crashes. You can simply delete the lock file in such
     cases.
     
    +.. warning::
    +
    +   **Security Consideration - TOCTOU Vulnerability**: On platforms without ``O_NOFOLLOW`` support
    +   (such as GraalPy), :class:`SoftFileLock <filelock.SoftFileLock>` may be vulnerable to symlink-based
    +   Time-of-Check-Time-of-Use (TOCTOU) attacks. An attacker with local filesystem access could create
    +   a symlink at the lock file path during the small race window between permission validation and file
    +   creation.
    +
    +   On most modern platforms with ``O_NOFOLLOW`` support, this vulnerability is mitigated by refusing
    +   to follow symlinks when creating the lock file.
    +
    +   For security-sensitive applications, prefer :class:`UnixFileLock <filelock.UnixFileLock>` or
    +   :class:`WindowsFileLock <filelock.WindowsFileLock>` which provide stronger guarantees via OS-level
    +   file locking. :class:`SoftFileLock <filelock.SoftFileLock>` should only be used as a fallback mechanism
    +   on platforms where OS-level locking primitives are unavailable.
    +
     Asyncio support
     ---------------
     
    
  • src/filelock/_soft.py+3 1 modified
    @@ -16,13 +16,15 @@ class SoftFileLock(BaseFileLock):
         def _acquire(self) -> None:
             raise_on_not_writable_file(self.lock_file)
             ensure_directory_exists(self.lock_file)
    -        # first check for exists and read-only mode as the open will mask this case as EEXIST
             flags = (
                 os.O_WRONLY  # open for writing only
                 | os.O_CREAT
                 | os.O_EXCL  # together with above raise EEXIST if the file specified by filename exists
                 | os.O_TRUNC  # truncate the file to zero byte
             )
    +        o_nofollow = getattr(os, "O_NOFOLLOW", None)
    +        if o_nofollow is not None:
    +            flags |= o_nofollow
             try:
                 file_handler = os.open(self.lock_file, flags, self._context.mode)
             except OSError as exception:  # re-raise unless expected exception
    
255ed068bc85

Fix TOCTOU symlink vulnerability in SoftFileLock

https://github.com/tox-dev/filelockBernát GáborJan 9, 2026via ghsa
2 files changed · +19 1
  • docs/index.rst+16 0 modified
    @@ -216,6 +216,22 @@ The :class:`SoftFileLock <filelock.SoftFileLock>` only watches the existence of
     portable, but also more prone to dead locks if the application crashes. You can simply delete the lock file in such
     cases.
     
    +.. warning::
    +
    +   **Security Consideration - TOCTOU Vulnerability**: On platforms without ``O_NOFOLLOW`` support
    +   (such as GraalPy), :class:`SoftFileLock <filelock.SoftFileLock>` may be vulnerable to symlink-based
    +   Time-of-Check-Time-of-Use (TOCTOU) attacks. An attacker with local filesystem access could create
    +   a symlink at the lock file path during the small race window between permission validation and file
    +   creation.
    +
    +   On most modern platforms with ``O_NOFOLLOW`` support, this vulnerability is mitigated by refusing
    +   to follow symlinks when creating the lock file.
    +
    +   For security-sensitive applications, prefer :class:`UnixFileLock <filelock.UnixFileLock>` or
    +   :class:`WindowsFileLock <filelock.WindowsFileLock>` which provide stronger guarantees via OS-level
    +   file locking. :class:`SoftFileLock <filelock.SoftFileLock>` should only be used as a fallback mechanism
    +   on platforms where OS-level locking primitives are unavailable.
    +
     Asyncio support
     ---------------
     
    
  • src/filelock/_soft.py+3 1 modified
    @@ -16,13 +16,15 @@ class SoftFileLock(BaseFileLock):
         def _acquire(self) -> None:
             raise_on_not_writable_file(self.lock_file)
             ensure_directory_exists(self.lock_file)
    -        # first check for exists and read-only mode as the open will mask this case as EEXIST
             flags = (
                 os.O_WRONLY  # open for writing only
                 | os.O_CREAT
                 | os.O_EXCL  # together with above raise EEXIST if the file specified by filename exists
                 | os.O_TRUNC  # truncate the file to zero byte
             )
    +        o_nofollow = getattr(os, "O_NOFOLLOW", None)
    +        if o_nofollow is not None:
    +            flags |= o_nofollow
             try:
                 file_handler = os.open(self.lock_file, flags, self._context.mode)
             except OSError as exception:  # re-raise unless expected exception
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.