new file mode 100644
@@ -0,0 +1,107 @@
+From eeceaa846cbe4df72718d94c8371ca1ab8f5b3cc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= <gaborjbernat@gmail.com>
+Date: Sat, 17 Oct 2026 02:21:17 -0700
+Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(soft):=20keep=20live=20holde?=
+ =?UTF-8?q?rs=20when=20owner=20identity=20differs=20(#836)?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+CVE: CVE-2026-112939
+Upstream-Status: Backport [https://github.com/tox-dev/filelock/commit/eeceaa846cbe4df72718d94c8371ca1ab8f5b3cc]
+
+Backport Changes:
+- Retain the 3.25 mode-opening API and mask group/other write bits.
+- Omit newer identity, namespace and Windows helper changes because
+ those interfaces are absent from the older two-line marker protocol.
+- Omit their newer tests and documentation; adapt the upstream mode
+ regression to the existing platform checks.
+
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ src/filelock/_soft.py | 7 ++++++-
+ tests/test_filelock.py | 31 ++++++++++++++++---------------
+ 2 files changed, 22 insertions(+), 16 deletions(-)
+
+diff --git a/src/filelock/_soft.py b/src/filelock/_soft.py
+index 8e2cde5..3a535ea 100644
+--- a/src/filelock/_soft.py
++++ b/src/filelock/_soft.py
+@@ -2,15 +2,20 @@ from __future__ import annotations
+
+ import os
+ import socket
++import stat
+ import sys
+ import time
+ from contextlib import suppress
+ from errno import EACCES, EEXIST, EPERM, ESRCH
+ from pathlib import Path
++from typing import Final
+
+ from ._api import BaseFileLock
+ from ._util import ensure_directory_exists, raise_on_not_writable_file
+
++#: Contenders act on the record in the marker, so no other account may write it, whatever the mode or umask.
++_OTHERS_WRITE: Final[int] = stat.S_IWGRP | stat.S_IWOTH
++
+ _WIN_SYNCHRONIZE = 0x100000
+ _WIN_ERROR_INVALID_PARAMETER = 87
+
+@@ -41,7 +46,7 @@ class SoftFileLock(BaseFileLock):
+ if (o_nofollow := getattr(os, "O_NOFOLLOW", None)) is not None:
+ flags |= o_nofollow
+ try:
+- file_handler = os.open(self.lock_file, flags, self._open_mode())
++ file_handler = os.open(self.lock_file, flags, self._open_mode() & ~_OTHERS_WRITE)
+ except OSError as exception:
+ if not (
+ exception.errno == EEXIST or (exception.errno == EACCES and sys.platform == "win32")
+diff --git a/tests/test_filelock.py b/tests/test_filelock.py
+index b7751c5..38c7b90 100644
+--- a/tests/test_filelock.py
++++ b/tests/test_filelock.py
+@@ -586,27 +586,28 @@ def test_lock_mode(tmp_path: Path) -> None:
+ lock.release()
+
+
+-def test_lock_mode_soft(tmp_path: Path) -> None:
+- # test soft lock permissions are dependent of umask
++@pytest.mark.skipif(sys.platform == "win32", reason="POSIX marker permission bits")
++@pytest.mark.parametrize(
++ ("mode", "umask"),
++ [
++ pytest.param(0o666, 0o022, id="explicit-mode"),
++ pytest.param(None, 0, id="default-mode-open-umask"),
++ ],
++)
++def test_lock_mode_soft_lets_only_the_owner_write_the_marker(
++ mode: int | None, umask: int, tmp_path: Path
++) -> None:
++ # Contenders act on the record inside, so no other account may rewrite it.
+ lock_path = tmp_path / "a.lock"
+- lock = SoftFileLock(str(lock_path), mode=0o666)
++ lock = SoftFileLock(str(lock_path)) if mode is None else SoftFileLock(str(lock_path), mode=mode)
+
+- # set umask so permissions can be anticipated
+- initial_umask = os.umask(0o022)
++ initial_umask = os.umask(umask)
+ try:
+- lock.acquire()
+- assert lock.is_locked
+-
+- mode = filemode(lock_path.stat().st_mode)
+- if sys.platform == "win32":
+- assert mode == "-rw-rw-rw-"
+- else:
+- assert mode == "-rw-r--r--"
++ with lock:
++ assert filemode(lock_path.stat().st_mode) == "-rw-r--r--"
+ finally:
+ os.umask(initial_umask)
+
+- lock.release()
+-
+
+ def test_umask(tmp_path: Path) -> None:
+ lock_path = tmp_path / "a.lock"
@@ -7,7 +7,9 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=2c6acbdf7bb74caa37512c3a5ca6857b"
CVE_PRODUCT = "tox-dev:filelock"
-SRC_URI += "file://run-ptest"
+SRC_URI += " file://run-ptest \
+ file://CVE-2026-112939.patch \
+"
SRC_URI[sha256sum] = "b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694"
BBCLASSEXTEND = "native nativesdk"