178 lines
5.1 KiB
Python
178 lines
5.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SKILL = ROOT / ".agents" / "skills" / "private-password-storage"
|
|
LAUNCHER = SKILL / "scripts" / "private-password-storage"
|
|
PYTHON_HELPER = SKILL / "scripts" / "private_password_storage.py"
|
|
SWIFT_HELPER = SKILL / "scripts" / "private_password_storage.swift"
|
|
|
|
|
|
def _fake_helper(tmp_path: Path) -> tuple[Path, Path]:
|
|
helper = tmp_path / "fake_keychain_helper.py"
|
|
capture = tmp_path / "captured_args.json"
|
|
helper.write_text(
|
|
"""#!/usr/bin/env python3
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
with open(os.environ["PRIVATE_PASSWORD_STORAGE_TEST_CAPTURE"], "w", encoding="utf-8") as handle:
|
|
json.dump(sys.argv[1:], handle)
|
|
|
|
if "--store" in sys.argv:
|
|
print("stored")
|
|
elif "--status" in sys.argv:
|
|
print("present")
|
|
elif "--delete-test-item" in sys.argv:
|
|
print("absent")
|
|
else:
|
|
print("error")
|
|
raise SystemExit(64)
|
|
""",
|
|
encoding="utf-8",
|
|
)
|
|
helper.chmod(0o700)
|
|
return helper, capture
|
|
|
|
|
|
def _run_fake(tmp_path: Path, action: str) -> tuple[subprocess.CompletedProcess[str], list[str]]:
|
|
helper, capture = _fake_helper(tmp_path)
|
|
env = os.environ.copy()
|
|
env["PRIVATE_PASSWORD_STORAGE_TEST_HELPER"] = str(helper)
|
|
env["PRIVATE_PASSWORD_STORAGE_TEST_CAPTURE"] = str(capture)
|
|
completed = subprocess.run(
|
|
[
|
|
str(LAUNCHER),
|
|
"--service",
|
|
"dev.codex.private-password-storage.canary.ci",
|
|
"--account",
|
|
"canary-ci",
|
|
"--label",
|
|
"CI fake credential",
|
|
action,
|
|
],
|
|
check=False,
|
|
capture_output=True,
|
|
text=True,
|
|
env=env,
|
|
)
|
|
return completed, json.loads(capture.read_text(encoding="utf-8"))
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("action", "expected", "returncode"),
|
|
[
|
|
("--store", "stored\n", 0),
|
|
("--status", "present\n", 0),
|
|
("--delete-test-item", "absent\n", 0),
|
|
],
|
|
)
|
|
def test_launcher_uses_only_metadata_and_action(
|
|
tmp_path: Path, action: str, expected: str, returncode: int
|
|
) -> None:
|
|
completed, captured = _run_fake(tmp_path, action)
|
|
|
|
assert completed.returncode == returncode
|
|
assert completed.stdout == expected
|
|
assert completed.stderr == ""
|
|
assert captured == [
|
|
"--service",
|
|
"dev.codex.private-password-storage.canary.ci",
|
|
"--account",
|
|
"canary-ci",
|
|
"--label",
|
|
"CI fake credential",
|
|
action,
|
|
]
|
|
|
|
|
|
def test_scripts_ban_unsafe_secret_paths_and_retrieval() -> None:
|
|
implementation = "\n".join(
|
|
path.read_text(encoding="utf-8")
|
|
for path in (LAUNCHER, PYTHON_HELPER, SWIFT_HELPER)
|
|
)
|
|
banned = (
|
|
"AppleScript",
|
|
"osascript",
|
|
"System Events",
|
|
"NSPasteboard",
|
|
"pbcopy",
|
|
"security add-generic-password",
|
|
"--get",
|
|
"--read-secret",
|
|
"--retrieve",
|
|
"kSecReturnData] = kCFBooleanTrue",
|
|
"kSecReturnAttributes",
|
|
"print(secret",
|
|
"print(password",
|
|
)
|
|
for token in banned:
|
|
assert token not in implementation
|
|
|
|
|
|
def test_swift_enforces_device_local_keychain_and_secure_popup() -> None:
|
|
source = SWIFT_HELPER.read_text(encoding="utf-8")
|
|
|
|
for required in (
|
|
"NSSecureTextField",
|
|
'title: "Paste"',
|
|
"keyEquivalentModifierMask = [.command]",
|
|
"guard !secureField.stringValue.isEmpty",
|
|
"kSecAttrAccessibleWhenUnlockedThisDeviceOnly",
|
|
"kSecAttrSynchronizable: kCFBooleanFalse",
|
|
"SecItemAdd",
|
|
"SecItemUpdate",
|
|
"SecItemCopyMatching",
|
|
"SecItemDelete",
|
|
'service.hasPrefix("dev.codex.private-password-storage.canary.")',
|
|
'account.hasPrefix("canary-")',
|
|
):
|
|
assert required in source
|
|
|
|
store_case = source.split("case .store:", 1)[1].split(
|
|
"case .deleteTestItem:", 1
|
|
)[0]
|
|
assert "runSecurePrompt" in store_case
|
|
assert "runSecurePrompt" not in source.split("case .status:", 1)[1].split(
|
|
"case .store:", 1
|
|
)[0]
|
|
|
|
|
|
def test_launcher_builds_an_ephemeral_identifiable_native_app() -> None:
|
|
source = PYTHON_HELPER.read_text(encoding="utf-8")
|
|
|
|
assert 'TemporaryDirectory(prefix="private-password-storage-")' in source
|
|
assert '"CFBundleIdentifier": "dev.codex.private-password-storage"' in source
|
|
assert '"CFBundlePackageType": "APPL"' in source
|
|
assert '"NSHighResolutionCapable": True' in source
|
|
assert '"/usr/bin/open"' in source
|
|
assert 'result_file = app.parent / "store-status"' in source
|
|
assert "secretData.write" not in SWIFT_HELPER.read_text(encoding="utf-8")
|
|
|
|
|
|
@pytest.mark.skipif(sys.platform != "darwin", reason="requires macOS AppKit SDK")
|
|
def test_embedded_swift_helper_typechecks() -> None:
|
|
target = f"{platform.machine()}-apple-macosx12.0"
|
|
completed = subprocess.run(
|
|
[
|
|
"/usr/bin/xcrun",
|
|
"swiftc",
|
|
"-target",
|
|
target,
|
|
"-typecheck",
|
|
str(SWIFT_HELPER),
|
|
],
|
|
check=False,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
assert completed.returncode == 0, completed.stderr
|