PyPI / filelock / 4.2.4

filelock 4.2.4

Source
https://github.com/tox-dev/py-filelock
Tag scanned
4.2.4
Compared with
4.2.3 (0 signals introduced since)
Files
95 scanned, 9 skipped (binary, oversized, or unrecognised)
Signals
0 critical · 1 warn · 22 info
Scan time
18.1 s
LLM review
Reviewed by claude-haiku-5-5 (Anthropic): 23 of 23 warn and critical signals; 22 demoted to info.
Disclude version
4.1.0
Scanned (UTC)
2026-10-21 22:20

Signals

Ordered by severity, then signals introduced in this release. Hidden characters are shown as ⟨U+…⟩.

  1. warn frame-introspection tasks/capabilities.py:230:13

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

                nested.append(True)
                sys.setprofile(sys.getprofile())
    
        sys.addaudithook(setprofile_again)
    likely benign LLM, confidence 0.68 An audit hook that re-applies the profile function so the probe's hook persists during nested checks.
    Reasoning

    An audit hook re-installs the profile function when setprofile is called, which is unusual. In a capability probe, it appears designed to keep the probe's hook in place for the nested test. The context is a test harness, so the behaviour looks like test scaffolding rather than persistence.

  2. info warn → info by review dynamic-execution compose.yaml:18:30

    [embedded bash] command name is a variable (`$$`) not set in this file — the caller or environment decides what runs (ast pass, confidence 0.70)

    "cp -a /repo \"$$HOME/work\" && cd \"$$HOME/work\" && pip install -q . && exec tox run -e py -x env.py.base_python=3.14 -x env_pkg_base.default_base_python=3.14"
    likely benign LLM, confidence 0.80 A Compose embedded bash snippet that copies the repo to a home-directory work area, installs it, and runs tox.
    Reasoning

    The embedded bash is a plain copy-repo, pip install, and tox run sequence. The `$$` is standard Compose escaping for a shell variable, so the variable command name is an environment-dependent reference rather than a hidden payload. The file looks like a CI or test helper.

  3. info warn → info by review dynamic-attribute src/filelock/__init__.py:124:5

    reach-by-name through `globals` (ast pass, confidence 0.60)

                value = getattr(module, f"Async{_FileLock.__name__}" if name == "AsyncFileLock" else name)
        globals()[name] = value
        return value
    likely benign LLM, confidence 0.90 A module-level lazy attribute loader that uses getattr and globals() to resolve names on demand.
    Reasoning

    The module-level globals() assignment and getattr lookup implement lazy attribute loading for public names such as AsyncFileLock. This is a common Python pattern for deferred imports and has no sign of concealment or malicious intent.

  4. info warn → info by review frame-introspection src/filelock/_api.py:1323:31

    `inspect.currentframe` — call-stack frame introspection (ast pass, confidence 0.70)

                    return
                state.releasing = inspect.currentframe()
                try:
                    _LOGGER.debug("Attempting to release lock %s on %s", id(self), self.lock_file)
    likely benign LLM, confidence 0.93 Records the current call frame on the lock object to track release re-entrancy.
    Reasoning

    inspect.currentframe() is stored on the lock's releasing state so the library can detect re-entrant release from the same frame. This is internal lock bookkeeping in a well-known locking library.

  5. info warn → info by review frame-introspection src/filelock/_api.py:1466:35

    `inspect.currentframe` — call-stack frame introspection (ast pass, confidence 0.70)

            attempt = 0
            self._context.acquiring = inspect.currentframe()
            try:
                # Created once, so a directory that disappears while the acquisition waits fails it, not builds a second
    likely benign LLM, confidence 0.93 Stores the current frame on the lock context during acquisition for re-entrancy tracking.
    Reasoning

    The current frame is saved on the context while acquisition is in progress, which is the same kind of re-entrancy bookkeeping as the release path. It is not dynamic execution or exfiltration.

  6. info warn → info by review frame-introspection src/filelock/_api.py:1775:14

    `inspect.currentframe` — call-stack frame introspection (ast pass, confidence 0.70)

            return False
        caller = inspect.currentframe()
        while caller is not None and caller is not frame:
            caller = caller.f_back
    likely benign LLM, confidence 0.93 Walks the call stack via f_back to find whether a target frame is an ancestor.
    Reasoning

    The code walks the f_back chain to check whether a given frame is on the call stack. This is ordinary stack inspection used to detect a caller's frame.

  7. info warn → info by review frame-introspection tasks/capabilities.py:182:5

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        previous: Final = sys.getprofile()
        sys.setprofile(interrupt)
        try:
            with suppress(KeyboardInterrupt), contextmanager(probe)():
    likely benign LLM, confidence 0.72 Temporarily installs a profile hook to probe interrupt behaviour during a capability check.
    Reasoning

    This is a test-tooling capability probe in a filelock repo. It installs a temporary profile hook to test whether interrupts or profiling affect locking, and restores the previous hook in a finally block. The profiler use is unusual but consistent with a dev harness, not an attack.

  8. info warn → info by review frame-introspection tasks/capabilities.py:187:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        finally:
            sys.setprofile(previous)
        return bool(finished)
    likely benign LLM, confidence 0.72 Restores the prior profile function after the probe finishes.
    Reasoning

    This is the restore step in the finally block of the same probe, reinstating the previous profile function. It is cleanup, not a sign of malicious behaviour.

  9. info warn → info by review frame-introspection tasks/capabilities.py:234:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        try:
            sys.setprofile(sys.getprofile())
        except RuntimeError:
            return False
    likely benign LLM, confidence 0.72 Probes whether setting the profile function is permitted, returning False on RuntimeError.
    Reasoning

    This re-reads and re-sets the current profile function and catches RuntimeError to detect whether profiling is permitted. It is a feature probe in the test tooling, with no sign of an attack.

  10. info warn → info by review frame-introspection tests/test_async_filelock.py:1525:5

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

    
        sys.setprofile(take_from_cache)
        try:
            AsyncFileLock(lock_path, is_singleton=True, thread_local=thread_local, run_in_executor=False)
    likely benign LLM, confidence 0.90 Installs a profile hook in a test to trigger and observe singleton cache lookups during lock construction.
    Reasoning

    The test installs a profile callback to intercept the cache lookup during construction of an AsyncFileLock singleton, then clears it. This is a targeted concurrency or reentrancy test and is typical in a locking library's test suite.

  11. info warn → info by review frame-introspection tests/test_async_filelock.py:1529:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        finally:
            sys.setprofile(None)
    
        with pytest.raises(Timeout):
    likely benign LLM, confidence 0.90 Clears the test profile hook in a finally block.
    Reasoning

    This is the cleanup in a finally block that clears the test profile hook, which is standard test hygiene.

  12. info warn → info by review frame-introspection tests/test_filelock.py:629:5

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

    
        sys.setprofile(take_from_cache)
        try:
            FileLock(lock_path, is_singleton=True, thread_local=thread_local)
    likely benign LLM, confidence 0.90 Installs a profile hook in a test to exercise the singleton cache path during FileLock construction.
    Reasoning

    The test uses a profile callback to hit the singleton cache path during FileLock construction, which is a standard way to test reentrancy in the library's own test suite.

  13. info warn → info by review frame-introspection tests/test_filelock.py:633:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        finally:
            sys.setprofile(None)
        return handed_out.pop()
    likely benign LLM, confidence 0.90 Resets the test profile hook in a finally block.
    Reasoning

    This is test cleanup that resets the profile hook in a finally block.

  14. info warn → info by review frame-introspection tests/test_filelock.py:1679:5

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        entered: Final[set[FrameType]] = set()
        sys.setprofile(interrupt)
        try:
            operation()
    likely benign LLM, confidence 0.90 Installs an interrupt profile hook around an operation in a lock test.
    Reasoning

    The test installs an interrupt-style profile callback around an operation to check that lock state holds up under an interrupt. It is a test of the library's own behaviour.

  15. info warn → info by review frame-introspection tests/test_filelock.py:1685:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        finally:
            sys.setprofile(None)
        return False
    likely benign LLM, confidence 0.90 Clears the interrupt profile hook after the test operation.
    Reasoning

    This is the finally-block cleanup that clears the test profile hook.

  16. info warn → info by review frame-introspection tests/test_read_write_unit.py:861:5

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

    
        sys.setprofile(look_up_while_closing)
        try:
            del lock
    likely benign LLM, confidence 0.90 Installs a profile hook that looks up the lock during its close, to test a reentrancy edge case.
    Reasoning

    The test sets a profile callback to look up the lock while it is closing, which probes a reentrancy edge case in the read-write lock. This is typical test instrumentation.

  17. info warn → info by review frame-introspection tests/test_read_write_unit.py:865:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        finally:
            sys.setprofile(None)
    
        with (looked_up[0].read_lock if mode == "read" else looked_up[0].write_lock)(), pytest.raises(Timeout):
    likely benign LLM, confidence 0.90 Clears the test profile hook in a finally block.
    Reasoning

    This is the finally-block cleanup of the test profile hook.

  18. info warn → info by review frame-introspection tests/test_soft_lease.py:488:9

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

        def read_compromise() -> None:
            sys.setprofile(pause_in_claim_creation)
            try:
                assert lease.compromise is None
    likely benign LLM, confidence 0.90 Test helper installs a profile hook to inject a pause during lease claim creation.
    Reasoning

    sys.setprofile is used in a test to pause a thread at a specific point during claim creation to force a race condition for testing. This is a legitimate testing technique in a test file for a lock library; no malicious behavior is evident.

  19. info warn → info by review frame-introspection tests/test_soft_lease.py:492:13

    `sys.setprofile` — call-stack frame introspection (ast pass, confidence 0.70)

            finally:
                sys.setprofile(None)
    
        reader: Final = Thread(target=read_compromise)
    likely benign LLM, confidence 0.90 Cleanup that removes the test profile hook after the race-condition read.
    Reasoning

    The matching sys.setprofile(None) in a finally block just uninstalls the test profile hook. This is test-harness cleanup with no malicious indicators.

  20. info warn → info by review frame-introspection tests/test_soft_lifetime_warning.py:47:28

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

            if entry_point == "constructor":
                warning_line = sys._getframe().f_lineno + 1
                lock_type(tmp_path / "test.lock", lifetime=10)
            else:
    likely benign LLM, confidence 0.92 Test records the current line number to verify a lifetime warning's location.
    Reasoning

    sys._getframe().f_lineno is used to compute the expected line number of a warning so the test can assert the warning points at the correct source line. Standard test technique in a lock library's test suite.

  21. info warn → info by review frame-introspection tests/test_soft_lifetime_warning.py:51:28

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

                lock = lock_type(tmp_path / "test.lock")
                warning_line = sys._getframe().f_lineno + 1
                lock.lifetime = 10
    likely benign LLM, confidence 0.92 Test captures the caller line number to check warning attribution.
    Reasoning

    Same pattern: sys._getframe() used to capture the expected warning line for assertion in a test. Benign introspection in test code.

  22. info warn → info by review frame-introspection tests/test_soft_lifetime_warning.py:139:28

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

            if entry_point == "constructor":
                warning_line = sys._getframe().f_lineno + 1
                lock_type(tmp_path / "test.lock", lifetime=10)
            else:
    likely benign LLM, confidence 0.92 Test captures line number to validate a lifetime warning's reported location.
    Reasoning

    Duplicate test pattern of sys._getframe().f_lineno for verifying warning location in a test; no malicious behavior.

  23. info warn → info by review frame-introspection tests/test_soft_lifetime_warning.py:143:28

    `sys._getframe` — call-stack frame introspection (ast pass, confidence 0.70)

                lock = lock_type(tmp_path / "test.lock")
                warning_line = sys._getframe().f_lineno + 1
                lock.lifetime = 10
    likely benign LLM, confidence 0.92 Test captures line number for lifetime-setter warning location check.
    Reasoning

    Same benign test-assertion use of sys._getframe for warning line verification in the lifetime setter path.

Reproduce This Scan

Run disclude locally to verify. Add --format sarif for SARIF output. Add --llm (with an API key in the environment) to include the LLM review.

cargo install disclude --version 4.1.0
git clone https://github.com/tox-dev/py-filelock py-filelock && cd py-filelock
git checkout 4.2.4
disclude scan --severity info --diff 4.2.3 .