Back to skills
SkillHub ClubRun DevOpsFull StackSecurity

shell-security-ultimate

Classify every shell command as SAFE, WARN, or CRIT before your agent runs it.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,083
Hot score
99
Updated
March 19, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B80.4

Install command

npx @skill-hub/cli install openclaw-skills-shell-security-ultimate

Repository

openclaw/skills

Skill path: skills/globalcaos/shell-security-ultimate

Classify every shell command as SAFE, WARN, or CRIT before your agent runs it.

Open repository

Best for

Primary workflow: Run DevOps.

Technical facets: Full Stack, Security.

Target audience: everyone.

License: MIT.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install shell-security-ultimate into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding shell-security-ultimate to shared team environments
  • Use shell-security-ultimate for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: shell-security-ultimate
version: 2.2.1
description: "Classify every shell command as SAFE, WARN, or CRIT before your agent runs it."
metadata:
  openclaw:
    owner: kn7623hrcwt6rg73a67xw3wyx580asdw
    category: security
    tags:
      - shell
      - command-classification
      - risk-management
      - agent-safety
    license: MIT
    notes:
      security: "Instruction-only skill that classifies shell commands before execution β€” it does NOT execute commands itself. Teaches the agent to label every command as SAFE, WARN, or CRIT and enforce approval gates. No binaries, no network calls, no credentials. All logic runs within the existing LLM context."
---

# Shell Security Ultimate

Your agent has root access. Every command it runs is one bad inference away from `rm -rf /` or `curl | bash` from a stranger's repo.

This skill won't let that happen.

## How It Works

Every shell command gets classified before execution:

- 🟒 **SAFE** β€” Read-only, harmless. Runs without friction.
- 🟑 **WARN** β€” Could modify state. Logged, flagged, your call.
- πŸ”΄ **CRIT** β€” Destructive or irreversible. Blocked until you say so.

No command runs unclassified. No silent `chmod 777`. No quiet `dd if=/dev/zero`. Your agent won't accidentally email your SSH keys, won't helpfully format a disk, and won't `DROP TABLE users` because it misread the task.

## What You Get

- **Pre-execution classification** for every command, every time
- **Detailed operation logs** so you see exactly what ran and why it was allowed
- **Full override control** β€” approve, deny, or escalate at any level

## Who It's For

Anyone giving an AI agent shell access and wanting to sleep at night.

*Clone it. Fork it. Break it. Make it yours.*

πŸ‘‰ Explore the full project: [github.com/globalcaos/clawdbot-moltbot-openclaw](https://github.com/globalcaos/clawdbot-moltbot-openclaw)


---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### _meta.json

```json
{
  "owner": "globalcaos",
  "slug": "shell-security-ultimate",
  "displayName": "Shell Security Ultimate",
  "latest": {
    "version": "2.2.1",
    "publishedAt": 1771659212940,
    "commit": "https://github.com/openclaw/skills/commit/fce8331077d42cc06127372f0d6ca92b9bd401c2"
  },
  "history": [
    {
      "version": "2.2.0",
      "publishedAt": 1771657505745,
      "commit": "https://github.com/openclaw/skills/commit/ac2c26e18f38d0ae6c047454636d13cd566ee18a"
    },
    {
      "version": "1.0.3",
      "publishedAt": 1771020574636,
      "commit": "https://github.com/openclaw/skills/commit/7f9dce2b10657fa1085127b241575c41c85d5505"
    },
    {
      "version": "1.0.2",
      "publishedAt": 1770816021861,
      "commit": "https://github.com/openclaw/skills/commit/4bed5dcc32ec10173a9b7a4fdf76ae44d86535b9"
    },
    {
      "version": "1.0.1",
      "publishedAt": 1770593709927,
      "commit": "https://github.com/openclaw/skills/commit/773d8d3bfb3afcdf2f889c9c41f33f290b440be2"
    },
    {
      "version": "1.0.0",
      "publishedAt": 1770528930543,
      "commit": "https://github.com/openclaw/skills/commit/05bf2f3beaadc201d90b5350f84ff36a36ce8b50"
    }
  ]
}

```

### scripts/cmd_display.py

```python
#!/usr/bin/env python3
# /// script
# requires-python = ">=3.9"
# ///
"""
Command Display Helper - Formats command execution output with colors and security levels.

Usage:
    python3 cmd_display.py <level> "<command>" "<purpose>" "<result>" [warning] [action]

Levels:
    safe     - 🟒 Read-only information gathering
    low      - πŸ”΅ Project file modifications
    medium   - 🟑 Configuration changes
    high     - 🟠 System-level changes
    critical - πŸ”΄ Potential data loss

Examples:
    python3 cmd_display.py safe "git status" "Check repo state" "$(git status --short)"
    python3 cmd_display.py low "touch file.txt" "Create file" "$(touch file.txt && echo 'βœ“ Created')"
    python3 cmd_display.py medium "npm install" "Install deps" "βœ“ 42 packages" "May take time"
"""
import sys
import re


class Colors:
    """ANSI color codes for terminal output."""
    RESET = '\033[0m'
    BOLD = '\033[1m'

    # Standard colors
    BLACK = '\033[30m'
    RED = '\033[31m'
    GREEN = '\033[32m'
    YELLOW = '\033[33m'
    BLUE = '\033[34m'
    MAGENTA = '\033[35m'
    CYAN = '\033[36m'
    WHITE = '\033[37m'

    # Bright colors
    BRIGHT_RED = '\033[91m'
    BRIGHT_GREEN = '\033[92m'
    BRIGHT_YELLOW = '\033[93m'
    BRIGHT_BLUE = '\033[94m'
    BRIGHT_CYAN = '\033[96m'


# Security level configurations
LEVELS = {
    'safe': {
        'emoji': '🟒',
        'color': Colors.GREEN,
        'name': 'SAFE',
        'desc': 'Read-only information gathering'
    },
    'low': {
        'emoji': 'πŸ”΅',
        'color': Colors.BLUE,
        'name': 'LOW',
        'desc': 'Project file modifications'
    },
    'medium': {
        'emoji': '🟑',
        'color': Colors.YELLOW,
        'name': 'MEDIUM',
        'desc': 'Configuration changes'
    },
    'high': {
        'emoji': '🟠',
        'color': Colors.BRIGHT_YELLOW,
        'name': 'HIGH',
        'desc': 'System-level changes'
    },
    'critical': {
        'emoji': 'πŸ”΄',
        'color': Colors.RED,
        'name': 'CRITICAL',
        'desc': 'Potential data loss'
    }
}


def strip_ansi(text: str) -> str:
    """Remove ANSI escape codes from text for length calculation."""
    ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
    return ansi_escape.sub('', text)


def summarize_output(output: str, max_chars: int = 80) -> str:
    """
    Condense multi-line output to a single summary line.
    
    Strategies:
    - Single line: return as-is (truncated if needed)
    - Multiple lines: count and summarize
    - Empty: return placeholder
    """
    if not output or not output.strip():
        return "(no output)"
    
    lines = output.strip().split('\n')
    
    if len(lines) == 1:
        line = lines[0].strip()
        if len(line) > max_chars:
            return line[:max_chars-3] + "..."
        return line
    
    # Multiple lines - create summary
    non_empty = [l for l in lines if l.strip()]
    first_line = non_empty[0].strip() if non_empty else ""
    
    if len(first_line) > 50:
        first_line = first_line[:47] + "..."
    
    return f"{first_line} (+{len(lines)-1} more lines)"


def format_command(
    level: str,
    command: str,
    purpose: str,
    result: str,
    warning: str = None,
    action: str = None
) -> None:
    """
    Format and print a command execution report.
    
    Output format (max 4 lines):
    1. Level + Command
    2. Result (βœ“/βœ—)
    3. Purpose
    4. Warning/Action (optional)
    """
    if level not in LEVELS:
        print(f"Error: Unknown level '{level}'. Use: {', '.join(LEVELS.keys())}", file=sys.stderr)
        sys.exit(1)

    config = LEVELS[level]
    
    # Determine result icon and color
    result_clean = result.strip() if result else ""
    if result_clean.startswith('βœ“') or result_clean.startswith('βœ”'):
        result_icon = 'βœ“'
        result_color = Colors.BRIGHT_GREEN
        result_text = result_clean.lstrip('βœ“βœ” ')
    elif result_clean.startswith('βœ—') or result_clean.startswith('✘') or result_clean.startswith('Error'):
        result_icon = 'βœ—'
        result_color = Colors.BRIGHT_RED
        result_text = result_clean.lstrip('βœ—βœ˜ ')
    else:
        # Auto-detect based on content
        result_icon = 'βœ“'
        result_color = Colors.BRIGHT_GREEN
        result_text = summarize_output(result_clean)

    # Line 1: Level + Command
    level_str = f"{config['name']}: {config['desc'].upper()}"
    print(f"{config['color']}{Colors.BOLD}{config['emoji']} {level_str}: {command}{Colors.RESET}")
    
    # Line 2: Result
    print(f"{Colors.BOLD}{result_color}{result_icon}{Colors.RESET}  {result_text}")
    
    # Line 3: Purpose
    print(f"{Colors.CYAN}πŸ“‹ {purpose}{Colors.RESET}")
    
    # Line 4: Warning or Action (optional, only one shown if both provided)
    if warning:
        print(f"{Colors.BRIGHT_RED}{Colors.BOLD}⚠️  {warning}{Colors.RESET}")
    elif action:
        print(f"{Colors.BRIGHT_YELLOW}πŸ‘‰ {action}{Colors.RESET}")


def main():
    if len(sys.argv) < 5:
        print(__doc__)
        print("\nUsage: cmd_display.py <level> <command> <purpose> <result> [warning] [action]")
        print(f"Levels: {', '.join(LEVELS.keys())}")
        sys.exit(1)

    level = sys.argv[1].lower()
    command = sys.argv[2]
    purpose = sys.argv[3]
    result = sys.argv[4]
    warning = sys.argv[5] if len(sys.argv) > 5 else None
    action = sys.argv[6] if len(sys.argv) > 6 else None

    format_command(level, command, purpose, result, warning, action)


if __name__ == '__main__':
    main()

```

### scripts/patch-openclaw.sh

```bash
#!/bin/bash
#
# Patch OpenClaw to wire up before_tool_call hooks
# This enables plugins to intercept and block tool execution
#
set -e

OPENCLAW_DIR="${OPENCLAW_DIR:-$HOME/src/clawdbot-moltbot-openclaw}"
TARGET_FILE="$OPENCLAW_DIR/src/agents/pi-tool-definition-adapter.ts"
PATCH_MARKER="// EXEC-DISPLAY-PATCH: before_tool_call hook"

echo "πŸ”§ OpenClaw before_tool_call Hook Patcher"
echo "========================================="
echo ""

# Check if OpenClaw directory exists
if [ ! -d "$OPENCLAW_DIR" ]; then
    echo "❌ OpenClaw directory not found: $OPENCLAW_DIR"
    echo "   Set OPENCLAW_DIR environment variable to your OpenClaw source path"
    exit 1
fi

# Check if target file exists
if [ ! -f "$TARGET_FILE" ]; then
    echo "❌ Target file not found: $TARGET_FILE"
    exit 1
fi

# Check if already patched
if grep -q "$PATCH_MARKER" "$TARGET_FILE"; then
    echo "βœ… Already patched! No changes needed."
    exit 0
fi

echo "πŸ“ Patching $TARGET_FILE..."

# Create backup
cp "$TARGET_FILE" "$TARGET_FILE.backup.$(date +%Y%m%d_%H%M%S)"
echo "   Backup created"

# Apply patch using sed
# 1. Add import at the top (after existing imports)
sed -i '/^import.*logger.*$/a import { getGlobalHookRunner } from "../plugins/hook-runner-global.js";' "$TARGET_FILE"

# 2. Add the hook call before tool.execute
# Find the line with "return await tool.execute" and insert hook code before it
sed -i '/return await tool\.execute(toolCallId, params, signal, onUpdate);/i\
        '"$PATCH_MARKER"'\
        const hookRunner = getGlobalHookRunner();\
        if (hookRunner) {\
          const hookResult = await hookRunner.runBeforeToolCall(\
            { toolName: normalizedName, params: params as Record<string, unknown> },\
            { toolName: normalizedName }\
          );\
          if (hookResult?.block) {\
            return jsonResult({\
              status: "error",\
              tool: normalizedName,\
              error: hookResult.blockReason ?? "Tool call blocked by plugin hook",\
            });\
          }\
        }\
        // END EXEC-DISPLAY-PATCH' "$TARGET_FILE"

echo "   Patch applied"

# Verify patch was applied
if grep -q "$PATCH_MARKER" "$TARGET_FILE"; then
    echo "βœ… Patch verified"
else
    echo "❌ Patch verification failed"
    exit 1
fi

# Rebuild
echo ""
echo "πŸ”¨ Rebuilding OpenClaw..."
cd "$OPENCLAW_DIR"

# Use pnpm if available, otherwise npm
if command -v pnpm &> /dev/null; then
    pnpm build
else
    npm run build
fi

echo ""
echo "βœ… Done! Restart the OpenClaw gateway to apply changes."
echo ""
echo "To restart:"
echo "  systemctl --user restart openclaw-gateway"
echo ""
echo "To verify the hook is working, check logs for:"
echo "  [exec-display] 🟒 SAFE: ..."

```

### scripts/unpatch-openclaw.sh

```bash
#!/bin/bash
#
# Remove the before_tool_call hook patch from OpenClaw
#
set -e

OPENCLAW_DIR="${OPENCLAW_DIR:-$HOME/src/clawdbot-moltbot-openclaw}"
TARGET_FILE="$OPENCLAW_DIR/src/agents/pi-tool-definition-adapter.ts"
PATCH_MARKER="EXEC-DISPLAY-PATCH"

echo "πŸ”§ OpenClaw Hook Patch Remover"
echo "=============================="
echo ""

# Check if patched
if ! grep -q "$PATCH_MARKER" "$TARGET_FILE"; then
    echo "βœ… Not patched. No changes needed."
    exit 0
fi

echo "πŸ“ Removing patch from $TARGET_FILE..."

# Remove the import line
sed -i '/getGlobalHookRunner.*hook-runner-global/d' "$TARGET_FILE"

# Remove the hook block (from PATCH_MARKER to END PATCH_MARKER)
sed -i '/'"$PATCH_MARKER"'/,/END EXEC-DISPLAY-PATCH/d' "$TARGET_FILE"

echo "   Patch removed"

# Verify
if grep -q "$PATCH_MARKER" "$TARGET_FILE"; then
    echo "❌ Removal verification failed - some patch remnants remain"
    exit 1
else
    echo "βœ… Patch removed successfully"
fi

# Rebuild
echo ""
echo "πŸ”¨ Rebuilding OpenClaw..."
cd "$OPENCLAW_DIR"

if command -v pnpm &> /dev/null; then
    pnpm build
else
    npm run build
fi

echo ""
echo "βœ… Done! Restart the OpenClaw gateway to apply changes."

```