Updated constraints due security reasons (triggered on 2026-04-27T14:20:13+00:00 by 9e4811270b5b5e727e088a839c9a4a928c488230)#265
Merged
Conversation
e4f5839 to
c7c249b
Compare
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.
Fixed dependency issues for Python 3.10
resolve_entities=True) allows untrusted XML input to read local files. ### Patches lxml 6.1.0 changes the default toresolve_entities='internal', thus disallowing local file access by default. ### Workarounds Setting theresolve_entitiesoption explicitly toresolve_entities='internal'orresolve_entities=Falsedisables the local file access. ### Resources Original report: https://bugs.launchpad.net/lxml/+bug/2146291 The default option was changed toresolve_entities='internal'for the normal XML and HTML parsers in lxml 5.0. The default was not changed foriterparse()andETCompatXMLParser()at the time. lxml 6.1 makes the safe option the default for all parsers.Fixed dependency issues for Python 3.11
resolve_entities=True) allows untrusted XML input to read local files. ### Patches lxml 6.1.0 changes the default toresolve_entities='internal', thus disallowing local file access by default. ### Workarounds Setting theresolve_entitiesoption explicitly toresolve_entities='internal'orresolve_entities=Falsedisables the local file access. ### Resources Original report: https://bugs.launchpad.net/lxml/+bug/2146291 The default option was changed toresolve_entities='internal'for the normal XML and HTML parsers in lxml 5.0. The default was not changed foriterparse()andETCompatXMLParser()at the time. lxml 6.1 makes the safe option the default for all parsers.Fixed dependency issues for Python 3.12
resolve_entities=True) allows untrusted XML input to read local files. ### Patches lxml 6.1.0 changes the default toresolve_entities='internal', thus disallowing local file access by default. ### Workarounds Setting theresolve_entitiesoption explicitly toresolve_entities='internal'orresolve_entities=Falsedisables the local file access. ### Resources Original report: https://bugs.launchpad.net/lxml/+bug/2146291 The default option was changed toresolve_entities='internal'for the normal XML and HTML parsers in lxml 5.0. The default was not changed foriterparse()andETCompatXMLParser()at the time. lxml 6.1 makes the safe option the default for all parsers.Fixed dependency issues for Python 3.13
resolve_entities=True) allows untrusted XML input to read local files. ### Patches lxml 6.1.0 changes the default toresolve_entities='internal', thus disallowing local file access by default. ### Workarounds Setting theresolve_entitiesoption explicitly toresolve_entities='internal'orresolve_entities=Falsedisables the local file access. ### Resources Original report: https://bugs.launchpad.net/lxml/+bug/2146291 The default option was changed toresolve_entities='internal'for the normal XML and HTML parsers in lxml 5.0. The default was not changed foriterparse()andETCompatXMLParser()at the time. lxml 6.1 makes the safe option the default for all parsers.Dependency issues not solved for Python 3.7
Request.post()an attacker can send a specially crafted multipart request to force significant temporary memory allocation even when the request is ultimately rejected. ----- Patch: aio-libs/aiohttp@cbb774freasonparameter when creating aResponsemay be able to inject extra headers or similar exploits. ### Impact In the unlikely situation that an application allows untrusted data to be used in the response'sreasonparameter, then an attacker could manipulate the response to send something different from what the developer intended. ----- Patch: aio-libs/aiohttp@53b35a2web.static(..., show_index=True), the resulting index pages do not escape file names. If users can upload files with arbitrary filenames to the static directory, the server is vulnerable to XSS attacks. ### Workaround We have always recommended using a reverse proxy server (e.g. nginx) for serving static files. Users following the recommendation are unaffected. Other users can disableshow_indexif unable to upgrade. ----- Patch: https://github.com/aio-libs/aiohttp/pull/8319/filesrequest.url.origin()may return a different value than the raw Host header, or what a reverse proxy interpreted it as., potentially resulting in some kind of security bypass. ----- Patch: aio-libs/aiohttp@9370b97_read_chunk_from_length()):diff diff --git a/aiohttp/multipart.py b/aiohttp/multipart.py index 227be605c..71fc2654a 100644 --- a/aiohttp/multipart.py +++ b/aiohttp/multipart.py @@ -338,6 +338,8 @@ class BodyPartReader: assert self._length is not None, "Content-Length required for chunked read" chunk_size = min(size, self._length - self._read_bytes) chunk = await self._content.read(chunk_size) + if self._content.at_eof(): + self._at_eof = True return chunk async def _read_chunk_from_stream(self, size: int) -> bytes:This does however introduce some very minor issues with handling form data. So, if possible, it would be recommended to also backport the changes in: aio-libs/aiohttp@cebe526 aio-libs/aiohttp@7eecdff aio-libs/aiohttp@f21c6f2Application.add_domain(). ----- Patch: aio-libs/aiohttp@e00ca3c Patch: aio-libs/aiohttp@53e2e6fAIOHTTP_NO_EXTENSIONSis enabled, then an attacker may be able to execute a request smuggling attack to bypass certain firewalls or proxy protections. ----- Patch: aio-libs/aiohttp@259edc3Request.post()method, an attacker may be able to freeze the server by exhausting the memory. ----- Patch: aio-libs/aiohttp@b7dbd35request.read()method in an endpoint, it may be possible for an attacker to cause the server to spend a moderate amount of blocking CPU time (e.g. 1 second) while processing the request. This could potentially lead to DoS as the server would be unable to handle other requests during that time. ----- Patch: aio-libs/aiohttp@dc3170b Patch: aio-libs/aiohttp@4ed97a4cookiesattribute is accessed in an application, then an attacker may be able to trigger a storm of warning-level logs using a specially crafted Cookie header. ---- Patch: aio-libs/aiohttp@64629a0web.static()(not recommended for production deployments), it may be possible for an attacker to ascertain the existence of path components. ------ Patch: aio-libs/aiohttp@f2a86fd-OorPYTHONOPTIMIZE=1), and the application includes a handler that uses theRequest.post()method, then an attacker may be able to execute a DoS attack with a specially crafted message. ------ Patch: aio-libs/aiohttp@bc1319econtent_typeparameter in aiohttp could use this to inject extra headers or similar exploits. ### Impact If an application allows untrusted data to be used for the multipartcontent_typeparameter when constructing a request, an attacker may be able to manipulate the request to send something other than what the developer intended. ----- Patch: aio-libs/aiohttp@9a6ada9public_key_from_numbers(orEllipticCurvePublicNumbers.public_key()),EllipticCurvePublicNumbers.public_key(),load_der_public_key()andload_pem_public_key()functions do not verify that the point belongs to the expected prime-order subgroup of the curve. This missing validation allows an attacker to provide a public key pointPfrom a small-order subgroup. This can lead to security issues in various situations, such as the most commonly used signature verification (ECDSA) and shared key negotiation (ECDH). When the victim computes the shared secret asS = [victim_private_key]Pvia ECDH, this leaks information aboutvictim_private_key mod (small_subgroup_order). For curves with cofactor > 1, this reveals the least significant bits of the private key. When these weak public keys are used in ECDSA , it's easy to forge signatures on the small subgroup. Only SECT curves are impacted by this. ## Credit This vulnerability was discovered by: - XlabAI Team of Tencent Xuanwu Lab - Atuin Automated Vulnerability Discovery Enginebar.example.comto validate against a wildcard leaf certificate for*.example.com, even if the leaf's parent certificate (or upwards) contained an excluded subtree constraint forbar.example.com. This behavior resulted from a gap between RFC 5280 (which defines Name Constraint semantics) and RFC 9525 (which defines service identity semantics): put together, neither states definitively whether Name Constraints should be applied to peer names. To close this gap, cryptography now conservatively rejects any validation where the peer name would be rejected by a name constraint if it were a SAN instead. In practice, exploitation of this bypass requires an uncommon X.509 topology, one that the Web PKI avoids because it exhibits these kinds of problems. Consequently, we consider this a medium-to-low impact severity. See CVE-2025-61727 for a similar bypass in Go'scrypto/x509. ## Remediation Users should upgrade to 46.0.6 or newer. ## Attribution Reporter: @1sealHash.update()), this could lead to buffer overflows. For example:python h = Hash(SHA256()) b.update(buf[::-1])would read past the end of the buffer on Python >3.11src/filelock/_unix.py:39-44): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWRfilelockpackage -SoftFileLockclass File:src/filelock/_soft.pylines 17-27 CWE: CWE-362, CWE-367, CWE-59 --- ## Description A TOCTOU race condition vulnerability exists in theSoftFileLockimplementation 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 betweenraise_on_not_writable_file()(permission check) andos.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 Scenario1. 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 usingSoftFileLockfor inter-process synchronization. Affected Users: - Applications usingfilelock.SoftFileLockdirectly - Applications using the fallbackFileLockon systems withoutfcntlsupport (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 theO_NOFOLLOWflag to prevent symlink following during lock file creation. Patched Version: Next release (commit: 255ed068bc85d1ef406e50a135e1459170dd1bf0) Mitigation Details: - TheO_NOFOLLOWflag is added conditionally and gracefully degrades on platforms without support - On platforms withO_NOFOLLOWsupport (most modern systems): symlink attacks are completely prevented - On platforms withoutO_NOFOLLOW(e.g., GraalPy): TOCTOU window remains but is documented Users should: - Upgrade to the patched version when available - For critical deployments, consider usingUnixFileLockorWindowsFileLockinstead of the fallbackSoftFileLock--- ## Workarounds Is there a way for users to fix or remediate the vulnerability without upgrading? For users unable to update immediately: 1. AvoidSoftFileLockin security-sensitive contexts - useUnixFileLockorWindowsFileLockwhen 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/directory3. 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)resolve_entities=True) allows untrusted XML input to read local files. ### Patches lxml 6.1.0 changes the default toresolve_entities='internal', thus disallowing local file access by default. ### Workarounds Setting theresolve_entitiesoption explicitly toresolve_entities='internal'orresolve_entities=Falsedisables the local file access. ### Resources Original report: https://bugs.launchpad.net/lxml/+bug/2146291 The default option was changed toresolve_entities='internal'for the normal XML and HTML parsers in lxml 5.0. The default was not changed foriterparse()andETCompatXMLParser()at the time. lxml 6.1 makes the safe option the default for all parsers.SGROUPtags can be corrupted by exceeding the Python recursion limit. Reporter: Alexis Challande, Trail of Bits Ecosystem Security Team ecosystem@trailofbits.com Affected versions: This issue only affects the pure-Python implementation of protobuf-python backend. This is the implementation whenPROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=pythonenvironment variable is set or the default when protobuf is used from Bazel or pure-Python PyPi wheels. CPython PyPi wheels do not use pure-Python by default. This is a Python variant of a previous issue affecting protobuf-java. ### Severity This is a potential Denial of Service. Parsing nested protobuf data creates unbounded recursions that can be abused by an attacker. ### Proof of Concept For reproduction details, please refer to the unit tests decoder_test.py and message_test ### Remediation and Mitigation A mitigation is available now. Please update to the latest available versions of the following packages: * protobuf-python(4.25.8, 5.29.5, 6.31.1)pyasn1library is vulnerable to a Denial of Service (DoS) attack caused by uncontrolled recursion when decoding ASN.1 data with deeply nested structures. An attacker can supply a crafted payload containing nestedSEQUENCE(0x30) orSET(0x31) tags with Indefinite Length (0x80) markers. This forces the decoder to recursively call itself until the Python interpreter crashes with aRecursionErroror consumes all available memory (OOM), crashing the host application. ### Details The vulnerability exists because the decoder iterates through the input stream and recursively callsdecodeFun(the decoding callback) for every nested component found, without tracking or limiting the recursion depth. Vulnerable Code Locations: 1.indefLenValueDecoder(Line 998):for component in decodeFun(substrate, asn1Spec, allowEoo=True, **options):This method handles indefinite-length constructed types. It sits inside awhile Trueloop and recursively calls the decoder for every nested tag. 2.valueDecoder(Lines 786 and 907):for component in decodeFun(substrate, componentType, **options):This method handles standard decoding when a schema is present. It contains two distinct recursive calls that lack depth checks: Line 786: Recursively decodes components ofSEQUENCEorSETtypes. Line 907: Recursively decodes elements ofSEQUENCE OForSET OFtypes. 4._decodeComponentsSchemaless(Line 661):for component in decodeFun(substrate, **options):This method handles decoding when no schema is provided. In all three cases,decodeFunis invoked without passing adepthparameter or checking against a globalMAX_ASN1_NESTINGlimit. ### PoCimport sys from pyasn1.codec.ber import decoder sys.setrecursionlimit(100000) print("[*] Generating Recursion Bomb Payload...") depth = 50_000 chunk = b'\x30\x80' payload = chunk * depth print(f"[*] Payload size: {len(payload) / 1024:.2f} KB") print("[*] Triggering Decoder...") try: decoder.decode(payload) except RecursionError: print("[!] Crashed: Recursion Limit Hit") except MemoryError: print("[!] Crashed: Out of Memory") except Exception as e: print(f"[!] Crashed: {e}")[*] Payload size: 9.77 KB [*] Triggering Decoder... [!] Crashed: Recursion Limit Hit### Impact - This is an unhandled runtime exception that typically terminates the worker process or thread handling the request. This allows a remote attacker to trivially kill service workers with a small payload (<100KB), resulting in a Denial of Service. Furthermore, in environments where recursion limits are increased, this leads to server-wide memory exhaustion. - Service Crash: Any service usingpyasn1to parse untrusted ASN.1 data (e.g., LDAP, SNMP, Kerberos, X.509 parsers) can be crashed remotely. - Resource Exhaustion: The attack consumes RAM linearly with the nesting depth. A small payload (<200KB) can consume hundreds of megabytes of RAM or exhaust the stack. ### Credits Vulnerability discovered by Kevin Tu of TMIR at ByteDance.requests.Session, if the first request to a given origin is made withverify=False, TLS certificate verification may remain disabled for all subsequent requests to that origin, even ifverify=Trueis explicitly specified later. This occurs because the underlying connection is reused from the session's connection pool, causing the initial TLS verification setting to persist for the lifetime of the pooled connection. As a result, applications may unintentionally send requests without certificate verification, leading to potential man-in-the-middle attacks and compromised confidentiality or integrity. This behavior affects versions ofrequestsprior to 2.32.0.trust_env=Falseon your Requests Session (docs). ### References psf/requests#6965 https://seclists.org/fulldisclosure/2025/Jun/2requests.utils.extract_zipped_paths()utility function uses a predictable filename when extracting files from zip archives into the system temporary directory. If the target file already exists, it is reused without validation. A local attacker with write access to the temp directory could pre-create a malicious file that would be loaded in place of the legitimate one. ### Affected usages Standard usage of the Requests library is not affected by this vulnerability. Only applications that callextract_zipped_paths()directly are impacted. ### Remediation Upgrade to at least Requests 2.33.0, where the library now extracts files to a non-deterministic location. If developers are unable to upgrade, they can setTMPDIRin their environment to a directory with restricted write access.Retryobject. The most common way to disable redirects is at the request level, as follows:python resp = urllib3.request("GET", "https://httpbin.org/redirect/1", redirect=False) print(resp.status) # 302However, it is also possible to disable redirects, for all requests, by instantiating aPoolManagerand specifyingretriesin a way that disable redirects:python import urllib3 http = urllib3.PoolManager(retries=0) # should raise MaxRetryError on redirect http = urllib3.PoolManager(retries=urllib3.Retry(redirect=0)) # equivalent to the above http = urllib3.PoolManager(retries=False) # should return the first response resp = http.request("GET", "https://httpbin.org/redirect/1")However, theretriesparameter is currently ignored, which means all the above examples don't disable redirects. ## Affected usages PassingretriesonPoolManagerinstantiation to disable redirects or restrict their number. By default, requests and botocore users are not affected. ## Impact Redirects are often used to exploit SSRF vulnerabilities. An application attempting to mitigate SSRF or open redirect vulnerabilities by disabling redirects at the PoolManager level will remain vulnerable. ## Remediation You can remediate this vulnerability with the following steps: * Upgrade to a patched version of urllib3. If your organization would benefit from the continued support of urllib3 1.x, please contact sethmichaellarson@gmail.com to discuss sponsorship or contribution opportunities. * Disable redirects at therequest()level instead of thePoolManager()level.Content-Encoding: gzip, zstd). However, the number of links in the decompression chain was unbounded allowing a malicious server to insert a virtually unlimited number of compression steps leading to high CPU usage and massive memory allocation for the decompressed data. ## Affected usages Applications and libraries using urllib3 version 2.5.0 and earlier for HTTP requests to untrusted sources unless they disable content decoding explicitly. ## Remediation Upgrade to at least urllib3 v2.6.0 in which the library limits the number of links to 5. If upgrading is not immediately possible, usepreload_content=Falseand ensure thatresp.headers["content-encoding"]contains a safe number of encodings before reading the response content.Content-Encodingheader (e.g.,gzip,deflate,br, orzstd). The library must read compressed data from the network and decompress it until the requested chunk size is met. Any resulting decompressed data that exceeds the requested amount is held in an internal buffer for the next read operation. The decompression logic could cause urllib3 to fully decode a small amount of highly compressed data in a single operation. This can result in excessive resource consumption (high CPU usage and massive memory allocation for the decompressed data; CWE-409) on the client side, even if the application only requested a small chunk of data. ### Affected usages Applications and libraries using urllib3 version 2.5.0 and earlier to stream large compressed responses or content from untrusted sources.stream(),read(amt=256),read1(amt=256),read_chunked(amt=256),readinto(b)are examples ofurllib3.HTTPResponsemethod calls using the affected logic unless decoding is disabled explicitly. ### Remediation Upgrade to at least urllib3 v2.6.0 in which the library avoids decompressing data that exceeds the requested amount. If your environment contains a package facilitating the Brotli encoding, upgrade to at least Brotli 1.2.0 or brotlicffi 1.2.0.0 too. These versions are enforced by theurllib3[brotli]extra in the patched versions of urllib3. ### Credits The issue was reported by @Cycloctane. Supplemental information was provided by @stamparm during a security audit performed by 7ASecurity and facilitated by OSTIF.Content-Encodingheader (e.g.,gzip,deflate,br, orzstd). When using the streaming API, the library decompresses only the necessary bytes, enabling partial content consumption. However, for HTTP redirect responses, the library would read the entire response body to drain the connection and decompress the content unnecessarily. This decompression occurred even before any read methods were called, and configured read limits did not restrict the amount of decompressed data. As a result, there was no safeguard against decompression bombs. A malicious server could exploit this to trigger excessive resource consumption on the client (high CPU usage and large memory allocations for decompressed data; CWE-409). ### Affected usages Applications and libraries using urllib3 version 2.6.2 and earlier to stream content from untrusted sources by settingpreload_content=Falsewhen they do not disable redirects. ### Remediation Upgrade to at least urllib3 v2.6.3 in which the library does not decode content of redirect responses whenpreload_content=False. If upgrading is not immediately possible, disable redirects by settingredirect=Falsefor requests to untrusted source.Pathmodule in both zipp and zipfile, such asjoinpath, the overloaded division operator, anditerdir. Although the infinite loop is not resource exhaustive, it prevents the application from responding. The vulnerability was addressed in version 3.19.1 of jaraco/zipp.Dependency issues not solved for Python 3.8
Request.post()an attacker can send a specially crafted multipart request to force significant temporary memory allocation even when the request is ultimately rejected. ----- Patch: aio-libs/aiohttp@cbb774freasonparameter when creating aResponsemay be able to inject extra headers or similar exploits. ### Impact In the unlikely situation that an application allows untrusted data to be used in the response'sreasonparameter, then an attacker could manipulate the response to send something different from what the developer intended. ----- Patch: aio-libs/aiohttp@53b35a2request.url.origin()may return a different value than the raw Host header, or what a reverse proxy interpreted it as., potentially resulting in some kind of security bypass. ----- Patch: aio-libs/aiohttp@9370b97Application.add_domain(). ----- Patch: aio-libs/aiohttp@e00ca3c Patch: aio-libs/aiohttp@53e2e6fRequest.post()method, an attacker may be able to freeze the server by exhausting the memory. ----- Patch: aio-libs/aiohttp@b7dbd35request.read()method in an endpoint, it may be possible for an attacker to cause the server to spend a moderate amount of blocking CPU time (e.g. 1 second) while processing the request. This could potentially lead to DoS as the server would be unable to handle other requests during that time. ----- Patch: aio-libs/aiohttp@dc3170b Patch: aio-libs/aiohttp@4ed97a4cookiesattribute is accessed in an application, then an attacker may be able to trigger a storm of warning-level logs using a specially crafted Cookie header. ---- Patch: aio-libs/aiohttp@64629a0web.static()(not recommended for production deployments), it may be possible for an attacker to ascertain the existence of path components. ------ Patch: aio-libs/aiohttp@f2a86fd-OorPYTHONOPTIMIZE=1), and the application includes a handler that uses theRequest.post()method, then an attacker may be able to execute a DoS attack with a specially crafted message. ------ Patch: aio-libs/aiohttp@bc1319econtent_typeparameter in aiohttp could use this to inject extra headers or similar exploits. ### Impact If an application allows untrusted data to be used for the multipartcontent_typeparameter when constructing a request, an attacker may be able to manipulate the request to send something other than what the developer intended. ----- Patch: aio-libs/aiohttp@9a6ada9src/filelock/_unix.py:39-44): ```python def _acquire(self) -> None: ensure_directory_exists(self.lock_file) open_flags = os.O_RDWR