Files
Violin a51aa00d06 Refactor playbooks and templates for improved evidence handling and research documentation
- Updated various playbooks to use `$ENG_DIR` for storing evidence files instead of hardcoded paths.
- Enhanced documentation in playbooks to include mandatory CVE and exploit research fields in hypotheses.
- Introduced a new `pty-safe-delivery.md` reference for safe file delivery practices over PTY.
- Added a `shell_ctrl.py` template for PTY shell control with safeguards against long commands and file transfers.
- Improved tests to validate new hypothesis fields and ensure compliance with updated playbook requirements.
- General cleanup and consistency improvements across playbooks and templates.
2026-07-13 21:10:43 +01:00

50 lines
1.6 KiB
Python

"""Safety contract for the documented PTY shell controller template."""
from __future__ import annotations
import hashlib
import importlib.util
from pathlib import Path
import pytest
TEMPLATE = Path(__file__).parents[2] / "skills" / "pentest" / "templates" / "shell_ctrl.py"
SPEC = importlib.util.spec_from_file_location("violin_shell_ctrl_template", TEMPLATE)
assert SPEC and SPEC.loader
shell_ctrl = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(shell_ctrl)
def test_controller_labels_victim_output_and_parses_exit(monkeypatch):
sent: list[str] = []
monkeypatch.setattr(shell_ctrl.secrets, "token_hex", lambda _: "fixed")
controller = shell_ctrl.PtyShellController(
sent.append,
lambda marker: f"uid=1000\n{marker}=7\n",
)
exit_code, output = controller.run("id")
assert exit_code == 7
assert output == "[VICTIM] uid=1000"
assert sent == ["id; printf '\\n__VIOLIN_DONE_fixed__=%s\\n' \"$?\""]
def test_controller_refuses_long_or_multiline_pty_delivery():
controller = shell_ctrl.PtyShellController(lambda _: None, lambda _: "")
with pytest.raises(ValueError, match="too long"):
controller.run("x" * shell_ctrl.MAX_PTY_LINE_BYTES)
with pytest.raises(ValueError, match="one command line"):
controller.run("id\nuname -a")
def test_sha256_matches_requires_exact_digest(tmp_path):
artifact = tmp_path / "payload.py"
content = b"print('safe')\n"
artifact.write_bytes(content)
digest = hashlib.sha256(content).hexdigest()
assert shell_ctrl.sha256_matches(str(artifact), digest)
assert not shell_ctrl.sha256_matches(str(artifact), "0" * 64)