How VulnClaw's TUI Workbench Validates Testing Scope Boundaries

VulnClaw's TUI workbench validates testing scope boundaries through a three-layer validation system that parses user input via the /scope command, normalizes action lists and port ranges, applies mode-specific defaults, and re-validates through the CLI parser before execution.

The Unclecheng-li/VulnClaw repository implements a defensive validation pipeline that prevents out-of-bounds targets or dangerous action combinations from reaching the penetration testing engine. This scope validation is centralized in the TuiState object and enforced through interactive parsing, mode-aware defaults, and CLI-level re-validation.

Three-Layer Validation Architecture

VulnClaw's validation operates at three distinct layers to ensure testing scope boundaries are never violated during task execution.

Interactive Input Parsing and Normalization

When an operator issues the /scope slash command, the TUI initiates a prompt-state machine that collects and validates fields before they enter the system state.

The _cmd_scope handler (lines 79-94 in vulnclaw/cli/tui.py) builds a list of scope fields including target, only_host, only_port, blocked_host, blocked_path, allow_actions, and block_actions. Each user response routes through _handle_prompt_response, which dispatches to specialized parsers:

  • Port validation: The _parse_optional_port function (lines 629-638) converts input to an integer and enforces the range 1-65535, raising ValueError(_("tui.error_invalid_port")) for out-of-bounds values.
  • Action list normalization: The _parse_action_csv function (lines 221-226) splits comma-separated strings, trims whitespace, and filters empty items to guarantee a clean list[str].

Mode-Aware Default Application

If the operator leaves action lists empty, the TUI automatically applies safety defaults based on the selected TuiMode (quick, standard, deep, or continuous).

The _effective_allow_actions and _effective_block_actions methods (lines 613-618 in vulnclaw/cli/tui.py) query the mode configuration from vulnclaw/config/settings.py. For example, quick mode defaults to allow_actions=("recon",) and block_actions=("exploit", "persistent", "post_exploitation"), ensuring high-risk actions are blocked even when the user specifies nothing.

CLI-Level Re-Validation

Before launching any task, the TUI constructs a TuiTaskDraft via _draft_from_state (lines 442-456), which consolidates validated scope data into CLI arguments. When the user executes /run or presses Start, the _cmd_start handler triggers _do_launch (lines 331-349), passing the draft to the CLI runner in vulnclaw/cli/main.py.

The CLI entry point re-applies the same validation constraints independently, ensuring that bypassing the TUI (or manually editing generated commands) cannot violate scope boundaries.

Core Validation Logic in vulnclaw/cli/tui.py

The primary validation implementation resides in vulnclaw/cli/tui.py, where state management and boundary checking are tightly coupled.

State Storage: The TuiState dataclass maintains the canonical scope definition, tracking target, only_* filters, blocked_* exclusions, and action allow-lists/block-lists.

Draft Generation: The _draft_from_state function transforms the validated state into a TuiTaskDraft object, which build_command_preview_args converts into executable command-line strings. This draft serves as the immutable boundary specification passed to the execution engine.

Error Handling: All user-facing validation errors reference translation keys in vulnclaw/i18n/en.json (and zh.json), such as tui.error_invalid_port, ensuring consistent localized feedback when boundaries are violated.

Practical Usage Examples

Setting a Valid Custom Scope

/scope host=example.com port=443 allow=recon,scan block=exploit
  • The _cmd_scope handler parses key-value pairs through _parse_scope_args.
  • port=443 passes _parse_optional_port validation (within 1-65535).
  • allow=recon,scan and block=exploit are normalized by _parse_action_csv into clean lists.

The dashboard displays the effective actions:

Allowed actions: recon, scan
Blocked actions: exploit

Using Quick Mode Defaults

/mode quick
/run
  • The quick mode defines allow_actions=("recon",) and block_actions=("exploit", "persistent", "post_exploitation") in TuiMode.
  • _effective_allow_actions and _effective_block_actions inject these defaults when the user omits explicit values.

The generated command preview becomes:

vulnclaw recon <target> --only-host example.com --only-port 443 --allow-actions recon --block-actions exploit,persistent,post_exploitation

Handling Invalid Port Input

/scope port=99999
  • _parse_optional_port raises ValueError with the translated message tui.error_invalid_port.
  • The TUI displays "Invalid port number" and prompts the user to retry, preventing the out-of-bounds value from entering TuiState.

Inspecting the Command Draft Programmatically

from vulnclaw.cli.tui import build_task_draft, build_state_from_options

state = build_state_from_options(
    target="10.0.0.5",
    mode="deep",
    only_host="10.0.0.5",
    only_port="443",
    allow_actions="recon,scan",
)
draft = build_task_draft(state)
print(draft.command_line)

# Output: vulnclaw scan 10.0.0.5 --only-host 10.0.0.5 --only-port 443 --allow-actions recon,scan

Summary

  • Interactive validation occurs immediately during /scope input parsing, enforcing valid port ranges (1-65535) and normalized action lists via _parse_optional_port and _parse_action_csv.
  • Mode-aware defaults automatically populate empty allow/block action lists from TuiMode configurations (quick, standard, deep, continuous) through _effective_allow_actions and _effective_block_actions.
  • CLI re-validation ensures the TuiTaskDraft created by _draft_from_state is checked again by vulnclaw/cli/main.py before execution, preventing scope bypasses.
  • Localized error reporting uses translation keys like tui.error_invalid_port stored in vulnclaw/i18n/en.json to provide immediate feedback on boundary violations.

Frequently Asked Questions

How does VulnClaw validate port numbers entered in the TUI?

VulnClaw validates ports through the _parse_optional_port function in vulnclaw/cli/tui.py (lines 629-638). This function attempts to convert the input string to an integer and verifies it falls within the valid TCP/UDP port range of 1 to 65535. If the value is outside this range or not a valid integer, the function raises a ValueError with the translation key tui.error_invalid_port, which the TUI renders as a localized error message prompting the user to correct the input.

What happens if I don't specify allow_actions or block_actions when setting scope?

When action lists are omitted, the TUI applies default values based on the currently selected TuiMode (quick, standard, deep, or continuous). The _effective_allow_actions and _effective_block_actions methods (lines 613-618) retrieve the appropriate defaults from the mode configuration in vulnclaw/config/settings.py. For instance, quick mode automatically blocks high-risk actions like exploit and persistent while allowing only recon, ensuring safe defaults even without explicit user input.

Can the TUI validation be bypassed by running VulnClaw commands directly?

No, the validation cannot be bypassed because the CLI entry point in vulnclaw/cli/main.py re-applies the same scope validation constraints independently of the TUI. When the TUI launches a task via _do_launch, it passes a TuiTaskDraft to the CLI runner, which re-parses and validates all arguments—including targets, ports, and actions—before executing the penetration testing job. This dual-layer validation ensures consistency whether the operator uses the interactive workbench or command-line interface.

Where are the error messages for validation failures defined?

All user-facing validation error messages are defined in the internationalization files located at vulnclaw/i18n/en.json and zh.json. The TUI references these messages via translation keys such as tui.error_invalid_port and tui.invalid_choice. When validation fails in functions like _parse_optional_port, the code raises exceptions with these keys, which the Textual UI front-end (vulnclaw/cli/tui_textual.py) renders into the user's selected language.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →