T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/tmux-manager.py:458
- Finding
- Shell Command Injection Through the Tail Target<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tmux-manager.py:458-468` **Vulnerability Type**: OS command injection through an unquoted shell command **Risk Level**: High ### Vulnerable Code ```python session_name = target.split(":")[0] if not session_exists(session_name): sys.exit(f"Error: session '{session_name}' is not running.") log_file = os.path.join(tempfile.gettempdir(), f"tmux-tail-{target.replace(':', '-')}.log") # Start piping pane output to log file subprocess.run( ["tmux", "pipe-pane", "-t", target, f"cat >> {log_file}"], check=True ) ``` ### Technical Analysis The `target` value originates from the user-controlled `-s SESSION[:WINDOW]` argument. Although the code verifies that the session portion exists, it does not validate the complete target or restrict characters in the window portion. The complete target is incorporated into `log_file`, which is then interpolated without shell quoting into the command supplied to `tmux pipe-pane`. The command passed to `pipe-pane` is interpreted by a shell. Consequently, shell metacharacters in a valid tmux window name, such as semicolons, redirection operators, command substitutions, or comment characters, can change the meaning of the command. Using a subprocess argument array only protects the outer invocation of `tmux`; it does not protect the nested command that tmux subsequently passes to a shell. ### Attack Path 1. The attacker creates, renames, or persuades the user to create a window in an existing tmux session with shell metacharacters in its name. 2. The attacker invokes or persuades the user to invoke: ```bash tmux-manager.py --tail -s 'work:x; touch PWNED; #' ``` 3. The session check validates only `work`, which is a legitimate running session. 4. The target-derived filename produces a nested shell command resembling: ```bash cat >> /tmp/tmux-tail-work-x; touch PWNED; #.log ``` 5. `tmux pipe-pane` executes the injected command in the securit ...[truncated 637 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Do not derive shell commands from an unvalidated tmux target. - Validate session and window identifiers against a strict allowlist before using them, for example a narrowly defined set of alphanumeric characters, underscores, periods, and hyphens. - Shell-quote any path passed to `tmux pipe-pane` with `shlex.quote()`: ```python import shlex pipe_command = f"cat >> {shlex.quote(log_file)}" subprocess.run(["tmux", "pipe-pane", "-t", target, pipe_command], check=True) ``` - Prefer a design that avoids a nested shell entirely, if supported by the tmux integration. - Resolve the supplied target through tmux and reject it if it does not exactly match an existing, expected session/window identifier. - Add regression tests using targets containing spaces, semicolons, command substitutions, redirection operators, quotes, and newline characters. ]]>
