File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -216,6 +216,22 @@ The :class:`SoftFileLock <filelock.SoftFileLock>` only watches the existence of
216216portable, but also more prone to dead locks if the application crashes. You can simply delete the lock file in such
217217cases.
218218
219+ .. warning ::
220+
221+ **Security Consideration - TOCTOU Vulnerability **: On platforms without ``O_NOFOLLOW `` support
222+ (such as GraalPy), :class: `SoftFileLock <filelock.SoftFileLock> ` may be vulnerable to symlink-based
223+ Time-of-Check-Time-of-Use (TOCTOU) attacks. An attacker with local filesystem access could create
224+ a symlink at the lock file path during the small race window between permission validation and file
225+ creation.
226+
227+ On most modern platforms with ``O_NOFOLLOW `` support, this vulnerability is mitigated by refusing
228+ to follow symlinks when creating the lock file.
229+
230+ For security-sensitive applications, prefer :class: `UnixFileLock <filelock.UnixFileLock> ` or
231+ :class: `WindowsFileLock <filelock.WindowsFileLock> ` which provide stronger guarantees via OS-level
232+ file locking. :class: `SoftFileLock <filelock.SoftFileLock> ` should only be used as a fallback mechanism
233+ on platforms where OS-level locking primitives are unavailable.
234+
219235Asyncio support
220236---------------
221237
Original file line number Diff line number Diff line change @@ -16,13 +16,15 @@ class SoftFileLock(BaseFileLock):
1616 def _acquire (self ) -> None :
1717 raise_on_not_writable_file (self .lock_file )
1818 ensure_directory_exists (self .lock_file )
19- # first check for exists and read-only mode as the open will mask this case as EEXIST
2019 flags = (
2120 os .O_WRONLY # open for writing only
2221 | os .O_CREAT
2322 | os .O_EXCL # together with above raise EEXIST if the file specified by filename exists
2423 | os .O_TRUNC # truncate the file to zero byte
2524 )
25+ o_nofollow = getattr (os , "O_NOFOLLOW" , None )
26+ if o_nofollow is not None :
27+ flags |= o_nofollow
2628 try :
2729 file_handler = os .open (self .lock_file , flags , self ._context .mode )
2830 except OSError as exception : # re-raise unless expected exception
You can’t perform that action at this time.
0 commit comments