forked from HAL9000/cleveragents-core
dd17d0f8e6
Add reference documentation for three new TUI features: - docs/reference/tui_shell_safety.md: Full reference for the shell danger detection subsystem (DangerousPatternDetector, ShellDangerLevel, DangerousPattern, DangerousCommandWarning, DEFAULT_PATTERNS registry). Covers all built-in patterns across CRITICAL/HIGH/MEDIUM/LOW levels, usage examples, and custom pattern extension. - docs/reference/tui_permission_question.md: Full reference for the inline PermissionQuestionWidget (issue #997). Documents InlinePermissionQuestion, PermissionRequestType, PermissionDecision, render_permission_question(), PermissionDecisionEvent, and PermissionQuestionWidget with key bindings and usage examples. - docs/reference/tui.md: Extended with First-Run Experience section (ActorSelectionOverlay, first_run helpers), Inline Permission Questions section, shell danger detection note in Shell Mode, updated module table, and links to new reference pages.
242 lines
9.0 KiB
Markdown
242 lines
9.0 KiB
Markdown
# TUI — Shell Danger Detection
|
|
|
|
The shell safety subsystem detects dangerous command patterns before execution
|
|
in the TUI shell mode (`!` prefix). When a dangerous pattern is matched, the
|
|
TUI surfaces a warning overlay so the user can confirm or abort before the
|
|
command runs.
|
|
|
|
Introduced in the [Unreleased] milestone (issue #1003).
|
|
See also [`tui.md`](tui.md) for the overall TUI architecture.
|
|
|
|
**Module**: `cleveragents.tui.shell_safety`
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
When the user types a shell command in the TUI (prefixed with `!`), the
|
|
`DangerousPatternDetector` scans the command against a configurable registry
|
|
of patterns before execution. If any patterns match, a warning is displayed
|
|
with the danger level and a description of the risk.
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ ⚠ Dangerous command detected │
|
|
│ │
|
|
│ [Critical] rm -rf / recursively deletes the entire filesystem │
|
|
│ root. This will destroy the operating system and all data. │
|
|
│ │
|
|
│ Command: rm -rf / │
|
|
│ │
|
|
│ [c] Cancel [p] Proceed anyway │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Domain Models
|
|
|
|
### `ShellDangerLevel`
|
|
|
|
**Module**: `cleveragents.tui.shell_safety.danger_level`
|
|
|
|
`IntEnum` classifying the severity of a dangerous shell command. Levels are
|
|
ordered so that numeric comparisons work naturally
|
|
(`level >= ShellDangerLevel.HIGH`).
|
|
|
|
| Value | Int | Description |
|
|
|-------|-----|-------------|
|
|
| `LOW` | 1 | Minor risk — generally recoverable side-effects (e.g. `chmod 777` on a single file) |
|
|
| `MEDIUM` | 2 | Moderate risk — can cause data loss or security exposure in common scenarios |
|
|
| `HIGH` | 3 | High risk — significant, hard-to-reverse damage (e.g. `dd if=`, `mkfs`) |
|
|
| `CRITICAL` | 4 | Critical risk — can destroy the entire system or create a fork bomb |
|
|
|
|
### `DangerousPattern`
|
|
|
|
**Module**: `cleveragents.tui.shell_safety.dangerous_pattern`
|
|
|
|
Immutable frozen dataclass describing a single dangerous shell pattern.
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `name` | `str` | — | Short human-readable identifier (e.g. `"rm_rf_root"`) |
|
|
| `pattern` | `str` | — | Regular expression matching the dangerous command text |
|
|
| `level` | `ShellDangerLevel` | — | Danger severity classification |
|
|
| `description` | `str` | — | Human-readable explanation of the risk |
|
|
| `case_sensitive` | `bool` | `False` | When `True`, the regex is compiled without `re.IGNORECASE` |
|
|
|
|
**Methods:**
|
|
|
|
| Method | Returns | Description |
|
|
|--------|---------|-------------|
|
|
| `matches(command)` | `bool` | `True` if `command` matches this pattern |
|
|
|
|
### `DangerousCommandWarning`
|
|
|
|
**Module**: `cleveragents.tui.shell_safety.warning`
|
|
|
|
Immutable frozen dataclass produced by `DangerousPatternDetector` when a
|
|
dangerous command is detected.
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `command` | `str` | The original command string that triggered the warning |
|
|
| `matched_pattern` | `DangerousPattern` | The pattern that matched |
|
|
| `danger_level` | `ShellDangerLevel` | Convenience alias for `matched_pattern.level` |
|
|
| `message` | `str` | Human-readable warning message for display |
|
|
|
|
**Class methods:**
|
|
|
|
| Method | Returns | Description |
|
|
|--------|---------|-------------|
|
|
| `from_pattern(command, pattern)` | `DangerousCommandWarning` | Construct a warning from a command and the matching pattern |
|
|
|
|
---
|
|
|
|
## `DangerousPatternDetector`
|
|
|
|
**Module**: `cleveragents.tui.shell_safety.pattern_detector`
|
|
|
|
Domain service that checks shell commands against a configurable registry of
|
|
dangerous patterns. Ships with built-in `DEFAULT_PATTERNS` but supports full
|
|
customisation.
|
|
|
|
### Constructor
|
|
|
|
```python
|
|
DangerousPatternDetector(patterns: list[DangerousPattern] | None = None)
|
|
```
|
|
|
|
When `patterns` is `None`, the built-in `DEFAULT_PATTERNS` are used.
|
|
|
|
### Registry Management
|
|
|
|
| Method | Returns | Description |
|
|
|--------|---------|-------------|
|
|
| `add_pattern(pattern)` | `None` | Append a pattern to the registry (checked in insertion order) |
|
|
| `remove_pattern(name)` | `bool` | Remove the pattern with the given name; returns `True` if removed |
|
|
| `replace_patterns(patterns)` | `None` | Replace the entire registry with a new list |
|
|
| `patterns` *(property)* | `tuple[DangerousPattern, ...]` | Read-only view of the current registry |
|
|
|
|
### Detection
|
|
|
|
| Method | Returns | Description |
|
|
|--------|---------|-------------|
|
|
| `check(command)` | `list[DangerousCommandWarning]` | All warnings for `command` (may be empty); ordered by insertion order |
|
|
| `check_first(command)` | `DangerousCommandWarning \| None` | First (highest-priority) warning, or `None` |
|
|
| `is_dangerous(command)` | `bool` | `True` if `command` matches any registered pattern |
|
|
| `max_danger_level(command)` | `ShellDangerLevel \| None` | Highest danger level matched, or `None` |
|
|
|
|
---
|
|
|
|
## Default Pattern Registry
|
|
|
|
**Module**: `cleveragents.tui.shell_safety.pattern_registry`
|
|
|
|
The `DEFAULT_PATTERNS` tuple ships with the following built-in patterns:
|
|
|
|
### Critical
|
|
|
|
| Name | Pattern | Description |
|
|
|------|---------|-------------|
|
|
| `rm_rf_root` | `rm -rf /` | Recursively deletes the entire filesystem root |
|
|
| `rm_rf_wildcard` | `rm -rf /*` or `rm -rf *` | Deletes large portions of the filesystem |
|
|
| `fork_bomb` | `:(){ :|:& };:` | Exhausts the process table, requiring a hard reboot |
|
|
|
|
### High
|
|
|
|
| Name | Pattern | Description |
|
|
|------|---------|-------------|
|
|
| `dd_if_device` | `dd if=` | Can overwrite disk devices or fill storage |
|
|
| `mkfs` | `mkfs` | Formats a filesystem, permanently erasing all data |
|
|
| `shred_device` | `shred /dev/` or `shred --remove` | Overwrites data in an unrecoverable way |
|
|
|
|
### Medium
|
|
|
|
| Name | Pattern | Description |
|
|
|------|---------|-------------|
|
|
| `chmod_777` | `chmod 777` | Grants world-readable/writable/executable permissions |
|
|
| `sudo_rm` | `sudo rm` | Runs `rm` with elevated privileges |
|
|
| `wget_pipe_sh` | `wget … \| sh` | Executes arbitrary remote code without inspection |
|
|
| `curl_pipe_sh` | `curl … \| sh` | Executes arbitrary remote code without inspection |
|
|
| `wget_pipe_bash` | `wget … \| bash` | Executes arbitrary remote code without inspection |
|
|
| `curl_pipe_bash` | `curl … \| bash` | Executes arbitrary remote code without inspection |
|
|
|
|
### Low
|
|
|
|
| Name | Pattern | Description |
|
|
|------|---------|-------------|
|
|
| `git_push_force` | `git push --force` | Overwrites remote history, causing data loss for collaborators |
|
|
| `chmod_recursive_permissive` | `chmod -R 6xx/7xx` | Exposes sensitive files to unintended access |
|
|
|
|
---
|
|
|
|
## Usage Examples
|
|
|
|
### Basic detection
|
|
|
|
```python
|
|
from cleveragents.tui.shell_safety.pattern_detector import DangerousPatternDetector
|
|
|
|
detector = DangerousPatternDetector()
|
|
|
|
# Check a command
|
|
warnings = detector.check("rm -rf /")
|
|
if warnings:
|
|
print(warnings[0].message)
|
|
# [Critical] Dangerous command detected: rm -rf / recursively deletes ...
|
|
|
|
# Quick boolean check
|
|
if detector.is_dangerous("sudo rm -rf /var/log"):
|
|
print("Dangerous!")
|
|
|
|
# Highest danger level
|
|
level = detector.max_danger_level("wget http://example.com/script.sh | bash")
|
|
print(level) # ShellDangerLevel.MEDIUM
|
|
```
|
|
|
|
### Custom patterns
|
|
|
|
```python
|
|
from cleveragents.tui.shell_safety.danger_level import ShellDangerLevel
|
|
from cleveragents.tui.shell_safety.dangerous_pattern import DangerousPattern
|
|
from cleveragents.tui.shell_safety.pattern_detector import DangerousPatternDetector
|
|
|
|
detector = DangerousPatternDetector()
|
|
|
|
# Add a custom pattern
|
|
detector.add_pattern(
|
|
DangerousPattern(
|
|
name="drop_database",
|
|
pattern=r"\bDROP\s+DATABASE\b",
|
|
level=ShellDangerLevel.CRITICAL,
|
|
description="DROP DATABASE permanently deletes the entire database.",
|
|
case_sensitive=False,
|
|
)
|
|
)
|
|
|
|
# Remove a built-in pattern
|
|
detector.remove_pattern("git_push_force")
|
|
```
|
|
|
|
---
|
|
|
|
## Integration with Shell Mode
|
|
|
|
The `DangerousPatternDetector` is invoked by the TUI shell mode handler
|
|
(`cleveragents.tui.input.shell_exec`) before any subprocess is started.
|
|
If `check_first()` returns a warning, the TUI presents a confirmation
|
|
overlay before proceeding.
|
|
|
|
The shell mode is entered by typing `!` at the prompt. See
|
|
[Shell Mode](tui.md#shell-mode) in the TUI reference for the full
|
|
shell mode documentation.
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [TUI Reference](tui.md) — overall TUI architecture and shell mode
|
|
- [TUI Permissions Screen](tui_permissions.md) — full-screen permission overlay
|
|
- [TUI Permission Question Widget](tui_permission_question.md) — inline permission widget
|