diff --git a/tools/sandbox-lint/src/sandbox_lint/__init__.py b/tools/sandbox-lint/src/sandbox_lint/__init__.py index e9cf173bc..a617166c7 100644 --- a/tools/sandbox-lint/src/sandbox_lint/__init__.py +++ b/tools/sandbox-lint/src/sandbox_lint/__init__.py @@ -121,15 +121,13 @@ def _normalise(path: str) -> str: - """Strip a single trailing slash so '~/.aws' and '~/.aws/' compare equal. + """Strip all trailing slashes so '~/.aws' and '~/.aws//' compare equal. - The sandbox treats both forms as the same directory; the validator - must too, otherwise the forbidden-list could be bypassed by a - trailing-slash variant. + The sandbox treats every trailing-slash count as the same directory; + the validator must too, otherwise the forbidden-list could be bypassed + by a multi-slash variant. """ - if path.endswith("/") and len(path) > 1: - return path[:-1] - return path + return path.rstrip("/") or "/" def _normalised_set(paths: list[str]) -> set[str]: diff --git a/tools/sandbox-lint/tests/test_validator.py b/tools/sandbox-lint/tests/test_validator.py index 791664835..497d95bdb 100644 --- a/tools/sandbox-lint/tests/test_validator.py +++ b/tools/sandbox-lint/tests/test_validator.py @@ -163,6 +163,7 @@ def test_invariant_missing_deny_read_root(baseline: dict[str, Any]) -> None: "~/.config/gcloud", "/", "~/", + "~/.ssh//", ], ) def test_invariant_allow_read_rejects_credential_paths(baseline: dict[str, Any], forbidden: str) -> None: @@ -181,6 +182,7 @@ def test_invariant_allow_read_rejects_credential_paths(baseline: dict[str, Any], "~/.gnupg", "~/.ssh", "~/.aws/", + "~/.aws//", ], ) def test_invariant_allow_write_rejects_credential_paths(baseline: dict[str, Any], forbidden: str) -> None: