mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-16 17:46:20 +00:00
* fix(sandbox): platform-aware Lark CLI runtime validation for Windows hosts The managed Lark CLI sandbox runtime validation and its tests assumed POSIX semantics that Windows hosts cannot satisfy, breaking the focused AIO/Lark CLI suites (5 failures on current main). - _validate_lark_cli_sandbox_runtime keeps the strict executable-bit contract on POSIX; on Windows it validates the Linux-only artifacts by content instead (ELF/PE/Mach-O image magic for linux-*/lark-cli, shebang for the bin/lark-cli launcher), since NTFS cannot represent the exec bit. - The AIO runtime-mounts test now asserts the explicit Windows credential contract: an owner-only inheritable DACL (via the existing PowerShell ACL resolvers) instead of exact 0o700 modes, which remain asserted on POSIX. - Accept-path runtime tests stage ELF-prefixed payloads so both platforms exercise realistic artifact content; the extractor's mode assertion is POSIX-only with a writability check on Windows. Focused suites: 5 failed / 162 passed -> 167 passed, 3 skipped on Windows 11; POSIX behavior unchanged (POSIX branches keep the original assertions). * refactor(tests): share Windows ACL resolvers via a helper module and cover the Windows shebang gate Review follow-ups on #5442: - Move the PowerShell ACL resolvers (_windows_acl_env/_windows_acl_sids/ _windows_acl_protected/_windows_acl_owner_sid) from tests/test_lark_cli_integration.py into tests/_windows_acl_helpers.py, following the existing shared-helper convention, so the aio suite no longer imports the full lark-cli integration module (which drags in app.gateway routers and the FastAPI TestClient at collection time). - Add test_managed_sandbox_runtime_rejects_launcher_without_shebang_on_windows: a launcher without a shebang plus ELF-magic binaries, with lark_cli.os monkeypatched via the existing Windows stub so the shebang-missing reject branch of _runtime_artifact_is_executable is covered on every platform. - Comment the rejects-non-executable prestaged-binary test to record that on Windows the rejection comes from the payload's non-magic content, since chmod() cannot clear the exec bit there. Focused suites: 168 passed / 3 skipped on Windows 11.
71 lines
2.8 KiB
Python
71 lines
2.8 KiB
Python
"""Shared Windows ACL inspection helpers for lark-cli credential tests.
|
|
|
|
These resolvers shell out to Windows PowerShell ``Get-Acl`` and translate ACEs
|
|
to raw SIDs so tests can assert the owner-only DACL contract that the
|
|
credential-tree hardener establishes on NTFS (where POSIX modes are not
|
|
representable). They are Windows-only; callers gate them on ``os.name == "nt"``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
def _windows_acl_env() -> dict[str, str]:
|
|
"""Return a PowerShell environment with a clean, ordered ``PSModulePath``.
|
|
|
|
The Codex runtime prepends a bundled PowerShell module path that shadows the
|
|
stock ``Microsoft.PowerShell.Security`` module, which makes ``Get-Acl`` fail
|
|
to autoload under ``-NoProfile``. Use the stock Windows PowerShell module path
|
|
so ACL inspection is reliable on any host.
|
|
"""
|
|
system_root = os.environ.get("SystemRoot", r"C:\Windows")
|
|
program_files = os.environ.get("ProgramFiles", r"C:\Program Files")
|
|
modules = f"{system_root}\\system32\\WindowsPowerShell\\v1.0\\Modules;{program_files}\\WindowsPowerShell\\Modules"
|
|
return {**os.environ, "PSModulePath": modules}
|
|
|
|
|
|
def _windows_acl_sids(path: Path) -> set[str]:
|
|
"""Return the SIDs granted on *path* (Windows-only, PowerShell resolver).
|
|
|
|
``icacls`` displays localized account names rather than raw SIDs, so we
|
|
translate each ACE IdentityReference back to a SID before asserting.
|
|
"""
|
|
cmd = "(Get-Acl -LiteralPath '" + str(path) + "').Access | ForEach-Object { $_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value }"
|
|
out = subprocess.run(
|
|
["powershell", "-NoProfile", "-Command", cmd],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
env=_windows_acl_env(),
|
|
)
|
|
return {line.strip() for line in out.stdout.splitlines() if line.strip()}
|
|
|
|
|
|
def _windows_acl_protected(path: Path) -> bool:
|
|
"""Return whether *path*'s DACL is protected from inheritance (Windows-only)."""
|
|
cmd = "(Get-Acl -LiteralPath '" + str(path) + "').AreAccessRulesProtected"
|
|
out = subprocess.run(
|
|
["powershell", "-NoProfile", "-Command", cmd],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
env=_windows_acl_env(),
|
|
)
|
|
return out.stdout.strip() == "True"
|
|
|
|
|
|
def _windows_acl_owner_sid(path: Path) -> str:
|
|
"""Return *path*'s object owner as a raw SID (Windows-only)."""
|
|
cmd = "$acl = Get-Acl -LiteralPath $env:DEER_FLOW_TEST_ACL_PATH; $acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value"
|
|
out = subprocess.run(
|
|
["powershell", "-NoProfile", "-Command", cmd],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
env={**_windows_acl_env(), "DEER_FLOW_TEST_ACL_PATH": str(path)},
|
|
)
|
|
return out.stdout.strip()
|