Module: Clacky::Tools::Security
- Defined in:
- lib/clacky/tools/security.rb
Overview
Pre-execution safety layer for shell-style commands.
Design principle: protect against the handful of commands that are irreversibly destructive or can compromise the host. Everything else is the user’s (or agent’s) business. Over-protection burns tool-call rounds and forces awkward work-arounds (e.g. the infamous “cp ~/.clacky /xxx ./ … Blocked: outside project directory” dance).
Responsibilities (applied to the ‘command` string BEFORE it is handed to a shell / PTY for execution):
1. Block hard-dangerous commands: sudo, pkill clacky, eval, exec,
`...`, $(...), | sh, | bash,
redirect to /etc /usr /bin.
2. Rewrite `rm` → `mv <file> <trash>` so the file is recoverable.
3. Rewrite `curl ... | bash` → save script to a file for manual
review instead of exec.
4. Protect credential/secret files: .env, .ssh/, .aws/ — block
writes to these only. Other
"project" files (Gemfile,
README.md, package.json, …)
are NOT protected — editing
them is a normal dev task.
Notes:
- `cp`, `mv`, `mkdir`, `touch`, `echo` are allowed to touch ANY path
(including outside the project root). The source of a `cp` is
read-only to the FS, and writing to arbitrary dirs is a legitimate
need (copying from ~/.clacky/skills/..., writing to /tmp, etc.).
Raises SecurityError on block. Returns a (possibly rewritten) command string on success.
This module was extracted from the former ‘SafeShell` tool. It is now shared by any tool that executes shell-style commands (currently: `terminal`).
Defined Under Namespace
Constant Summary collapse
- SAFE_READONLY_COMMANDS =
Read-only commands that are considered safe for auto-execution (permission mode :confirm_safes).
%w[ ls pwd cat less more head tail grep find which whereis whoami ps top htop df du git echo printf wc date file stat env printenv curl wget ].freeze
Class Method Summary collapse
-
.command_safe_for_auto_execution?(command) ⇒ Boolean
True iff the command is safe to auto-execute in :confirm_safes mode.
-
.make_safe(command, project_root: Dir.pwd) ⇒ String
Process ‘command` and return a (possibly rewritten) safe version.
Class Method Details
.command_safe_for_auto_execution?(command) ⇒ Boolean
True iff the command is safe to auto-execute in :confirm_safes mode. (Either a known read-only command, or one that Security.make_safe returns unchanged.)
77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/clacky/tools/security.rb', line 77 def command_safe_for_auto_execution?(command) return false unless command cmd_name = command.strip.split.first return true if SAFE_READONLY_COMMANDS.include?(cmd_name) begin safe = make_safe(command, project_root: Dir.pwd) command.strip == safe.strip rescue SecurityError false end end |
.make_safe(command, project_root: Dir.pwd) ⇒ String
Process ‘command` and return a (possibly rewritten) safe version. Raises SecurityError when the command cannot be made safe.
70 71 72 |
# File 'lib/clacky/tools/security.rb', line 70 def make_safe(command, project_root: Dir.pwd) Replacer.new(project_root).make_command_safe(command) end |