Skip to content

Sanitize task prompt in dispatch tmux command — HUB_TASK_PROMPT shell injection #310

@ooloth

Description

@ooloth

Current state

When hub dispatches a task, task_prompt — built from user-authored title, description, comments, and linked GitHub content — is embedded directly into a tmux -e argument via format!("HUB_TASK_PROMPT={task_prompt}"). The spawned shell command then references it as "$HUB_TASK_PROMPT". A task field containing a double-quote followed by shell metacharacters (e.g. "; touch /tmp/pwned; echo ") closes the shell quoting prematurely, allowing arbitrary shell commands to execute when the dispatch window opens.

The same pattern is present in ui/tui/src/investigations/launch.rs line 113, where the prompt value is built from external GitHub API data (PR body, issue body, CI log content) and embedded the same way. API-sourced content containing a double-quote or $() can break shell quoting in the spawned investigation window.

Ideal state

  • HUB_TASK_PROMPT is never referenced inline inside a shell-quoted command string; the shell command reads it from the environment without quoting that reference inside another shell.
  • Alternatively, the prompt is written to a temp file (as supporting_data already does in launch.rs lines 75–84) and only the file path — a controlled value — appears in the shell command string.
  • A task description containing any combination of shell metacharacters cannot alter the commands executed when the dispatch or investigation window opens.

Starting points

  • workflows/src/dispatch.rs lines 480–498 — format!("HUB_TASK_PROMPT={task_prompt}") passed as tmux -e arg and the shell command string that references it as "$HUB_TASK_PROMPT"
  • ui/tui/src/investigations/launch.rs line 113 — same pattern for the investigation prompt built from GitHub API data

QA plan

  1. Create a task whose description is "; touch /tmp/hub-injection-test; echo ". Dispatch it. Check whether /tmp/hub-injection-test was created — expect it was not.
  2. Verify the dispatch window opens the expected claude session normally with the task context intact.
  3. Repeat with a task description containing $(whoami) and confirm the subcommand is not executed.
  4. For investigation launch: mock a GitHub PR body containing "; touch /tmp/hub-investigation-test; echo ". Open an investigation. Confirm no file was created.

Done when

No content of any task field or GitHub API response can execute as shell syntax in the dispatch or investigation tmux command.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions