Skip to content

7.13.3 raises PermissionError when workspace is in a path with restricted parent directories #2129

@ausarb

Description

@ausarb

Describe the bug
Coverage 7.13.3 raises PermissionError when the project workspace is nested under a directory the user doesn't have read access to. The new virtualenv detection code in _analyze_directory() walks up parent directories and fails when it encounters a restricted directory.

This is a regression introduced by the fix for #2082.

To Reproduce

  1. What version of Python are you using?
    Python 3.10
  2. What version of coverage.py shows the problem?
    7.13.3 (released 2026-02-03). Version 7.13.2 works fine.
  3. What versions of what packages do you have installed?
    • coverage==7.13.3
    • pytest==7.4.4
    • pytest-cov==6.2.1
  4. What code shows the problem?
    Any project will reproduce this. The issue is the directory structure, not the code.
  5. What commands should we run to reproduce the problem?
    docker run -it --rm python:3.10 bash -c '
    mkdir -p /home/restricted.domain/user/workspace
    useradd -m testuser
    chown -R testuser:testuser /home/restricted.domain/user
    chown root:root /home/restricted.domain
    chmod 711 /home/restricted.domain
    su testuser -c "
    cd /home/restricted.domain/user/workspace
    python -m venv .venv
    . .venv/bin/activate
    pip install -q pytest pytest-cov coverage==7.13.3
    mkdir src tests
    touch src/__init__.py
    echo \"def hello(): return 'world'\" > src/app.py
    echo \"from src.app import hello
    def test_hello(): assert hello() == 'world'\" > tests/test_app.py
    pytest --cov=src tests/
    "
    '

Expected behavior
Coverage should handle inaccessible parent directories gracefully, either by catching PermissionError or stopping the upward traversal when access is denied.

Additional context
This affects CI environments where the build user's home directory is under a domain-based path (e.g., /home/domain.com/builduser/...) where the intermediate directory (/home/domain.com) exists but isn't readable.

The error occurs in inorout.py at line 182 in _analyze_directory(), called from set_matchers_depending_on_syspath().

Workaround: Pin to coverage==7.13.2
Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions