Module: Clacky::Tools::Security

Defined in:
lib/clacky/tools/security.rb

Overview

Pre-execution safety layer for shell-style commands.

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 important files:             Gemfile, Gemfile.lock, .env,
                                        package.json, yarn.lock,
                                        .ssh/, .aws/, .gitignore,
                                        README.md, LICENSE.
5. Confine writes to project_root.      `mv`, `cp`, `mkdir` targets
                                        outside the project tree are
                                        blocked.

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

Classes: Blocked, Replacer

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

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.)

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/clacky/tools/security.rb', line 66

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.

Parameters:

  • command (String)

    command to check

  • project_root (String) (defaults to: Dir.pwd)

    path treated as the allowed root for writes

Returns:

  • (String)

    safe command to execute



59
60
61
# File 'lib/clacky/tools/security.rb', line 59

def make_safe(command, project_root: Dir.pwd)
  Replacer.new(project_root).make_command_safe(command)
end