Skip to content

Commit f72dddf

Browse files
authored
test(input): inject secure-open failures on the primitive the platform uses (#503)
Two cases prove the failed-secure-open contract by patching skillspector.input_handler.os.open. _HAS_SECURE_DIR_FD is False on Windows, so _open_regular_file_no_follow dispatches to _open_regular_file_from_windows_handle and os.open is never called. The failure is never injected there: the file is read normally, and both cases fail while asserting the contract they exist to protect. Deny both primitives so the failure reaches the dispatcher on either platform. The Windows stub raises _FileOpenError, which is what the real helper raises when CreateFileW fails. Signed-off-by: kevin9327 <kevin9327@users.noreply.github.com> Co-authored-by: kevin9327 <kevin9327@users.noreply.github.com>
1 parent 9c546dc commit f72dddf

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

‎tests/nodes/test_build_context.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,7 +1471,13 @@ def test_build_context_reports_read_error_without_fake_empty_content(
14711471
def deny_open(*args: object, **kwargs: object) -> int:
14721472
raise PermissionError("sensitive operating-system detail")
14731473

1474+
# The secure open dispatches on the platform: POSIX goes through os.open,
1475+
# Windows through the handle-based helper. Deny both so the failure is
1476+
# injected wherever the test happens to run.
14741477
monkeypatch.setattr("skillspector.input_handler.os.open", deny_open)
1478+
monkeypatch.setattr(
1479+
"skillspector.input_handler._open_regular_file_from_windows_handle", deny_open
1480+
)
14751481
result = build_context({"skill_path": str(tmp_path)})
14761482

14771483
assert "broken.py" in result["components"]

‎tests/unit/test_input_handler.py‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from skillspector.input_handler import (
2929
ALLOWED_GIT_HOSTS,
3030
InputHandler,
31+
_FileOpenError,
3132
_open_regular_file_from_windows_handle,
3233
_open_regular_file_no_follow,
3334
)
@@ -236,8 +237,18 @@ def test_resolve_file_open_failure_does_not_create_temp_dir(tmp_path: Path) -> N
236237
source = tmp_path / "SKILL.md"
237238
source.write_text("# Skill", encoding="utf-8")
238239
handler = InputHandler()
240+
denied = OSError("denied")
239241
try:
240-
with patch("skillspector.input_handler.os.open", side_effect=OSError("denied")):
242+
# The secure open dispatches on the platform: POSIX goes through os.open,
243+
# Windows through the handle-based helper. Deny both so the failure is
244+
# injected wherever the test happens to run.
245+
with (
246+
patch("skillspector.input_handler.os.open", side_effect=denied),
247+
patch(
248+
"skillspector.input_handler._open_regular_file_from_windows_handle",
249+
side_effect=_FileOpenError(source, denied),
250+
),
251+
):
241252
with pytest.raises(ValueError, match="Could not safely open"):
242253
handler.resolve(str(source))
243254
assert handler.temp_dir_for_cleanup() is None

0 commit comments

Comments
 (0)