Repository: pypa/pip
File: tests/unit/test_self_check_outdated.py (Python)

Code before:
        expected_path = (
            cache_dir
            / "selfcheck"
            / self_outdated_check._get_statefile_name(sys.prefix)
        )

        # WHEN
        state = self_outdated_check.SelfCheckState(cache_dir=str(cache_dir))
        state.set(
            "1.0.0",
            datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc),
        )

        # THEN
        assert state._statefile_path == os.fspath(expected_path)

        contents = expected_path.read_text()
        assert json.loads(contents) == {
            "key": sys.prefix,
            "last_check": "2000-01-01T00:00:00+00:00",
            "pypi_version": "1.0.0",
        }

        statefile_permissions = os.stat(expected_path).st_mode & 0o666
        selfcheckdir_permissions = os.stat(cache_dir / "selfcheck").st_mode & 0o666
        assert statefile_permissions == selfcheckdir_permissions


@patch("pip._internal.self_outdated_check._self_version_check_logic")
def test_suppressed_by_externally_managed(mocked_function: Mock, tmpdir: Path) -> None:
    mocked_function.return_value = UpgradePrompt(old="1.0", new="2.0")
    fake_options = Values({"cache_dir": str(tmpdir)})
    with patch(
        "pip._internal.self_outdated_check.check_externally_managed",
        side_effect=ExternallyManagedEnvironment("nope"),
    ):
        pip_self_version_check(session=Mock(), options=fake_options)
    mocked_function.assert_not_called()


Review comment (security):
```suggestion
		# Check that the self-check cache entries inherit the root cache permissions.
        statefile_permissions = os.stat(expected_path).st_mode & 0o666
        selfcheckdir_permissions = os.stat(cache_dir / "selfcheck").st_mode & 0o666
        cache_permissions = os.stat(cache_dir).st_mode & 0o666
        assert statefile_permissions == selfcheckdir_permissions == cache_permissions
```

Let's add a comment and also check against the root `.cache` folder permissions as that's how the inheritance works with the network cache. 

Code after:
        expected_path = (
            cache_dir
            / "selfcheck"
            / self_outdated_check._get_statefile_name(sys.prefix)
        )

        # WHEN
        state = self_outdated_check.SelfCheckState(cache_dir=str(cache_dir))
        state.set(
            "1.0.0",
            datetime.datetime(2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc),
        )

        # THEN
        assert state._statefile_path == os.fspath(expected_path)

        contents = expected_path.read_text()
        assert json.loads(contents) == {
            "key": sys.prefix,
            "last_check": "2000-01-01T00:00:00+00:00",
            "pypi_version": "1.0.0",
        }
        # Check that the self-check cache entries inherit the root cache permissions.
        statefile_permissions = os.stat(expected_path).st_mode & 0o666
        selfcheckdir_permissions = os.stat(cache_dir / "selfcheck").st_mode & 0o666
        cache_permissions = os.stat(cache_dir).st_mode & 0o666
        assert statefile_permissions == selfcheckdir_permissions == cache_permissions


@patch("pip._internal.self_outdated_check._self_version_check_logic")
def test_suppressed_by_externally_managed(mocked_function: Mock, tmpdir: Path) -> None:
    mocked_function.return_value = UpgradePrompt(old="1.0", new="2.0")
    fake_options = Values({"cache_dir": str(tmpdir)})
    with patch(
        "pip._internal.self_outdated_check.check_externally_managed",
        side_effect=ExternallyManagedEnvironment("nope"),
    ):
        pip_self_version_check(session=Mock(), options=fake_options)
    mocked_function.assert_not_called()