{"id":50824402,"url":"https://github.com/scross01/hermes-custom-dangerous-patterns-plugin","last_synced_at":"2026-07-15T18:05:15.440Z","repository":{"id":362366434,"uuid":"1257752721","full_name":"scross01/hermes-custom-dangerous-patterns-plugin","owner":"scross01","description":"A Hermes Agent plugin that adds custom dangerous command patterns to the built-in approval system. Define regex patterns in YAML to gate destructive CLI commands (cloud CLIs, deploys, database ops) behind an explicit allow/deny approval prompt.","archived":false,"fork":false,"pushed_at":"2026-06-23T11:44:27.000Z","size":431,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T22:05:04.426Z","etag":null,"topics":["hermes-agent","hermes-plugin"],"latest_commit_sha":null,"homepage":"https://github.com/scross01/hermes-custom-dangerous-patterns-plugin/wiki","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scross01.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-03T01:25:54.000Z","updated_at":"2026-06-24T03:55:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/scross01/hermes-custom-dangerous-patterns-plugin","commit_stats":null,"previous_names":["scross01/hermes-custom-dangerous-patterns-plugin"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/scross01/hermes-custom-dangerous-patterns-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scross01%2Fhermes-custom-dangerous-patterns-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scross01%2Fhermes-custom-dangerous-patterns-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scross01%2Fhermes-custom-dangerous-patterns-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scross01%2Fhermes-custom-dangerous-patterns-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scross01","download_url":"https://codeload.github.com/scross01/hermes-custom-dangerous-patterns-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scross01%2Fhermes-custom-dangerous-patterns-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35515521,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-15T02:00:06.706Z","response_time":131,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hermes-agent","hermes-plugin"],"created_at":"2026-06-13T17:01:12.842Z","updated_at":"2026-07-15T18:05:15.420Z","avatar_url":"https://github.com/scross01.png","language":"Python","funding_links":[],"categories":["Skills \u0026 Plugins"],"sub_categories":["Plugins"],"readme":"# Custom Dangerous Patterns plugin for Hermes Agent\n\n\u003e **⚠️ USE AT YOUR OWN RISK**\n\u003e\n\u003e This plugin is in **early development** and has not been rigorously tested\n\u003e across all Hermes environments, versions, or edge cases. There is **no\n\u003e guarantee** that all destructive commands will be caught or blocked. Pattern\n\u003e matching is best-effort — creative command obfuscation, shell expansions,\n\u003e piped commands, or edge cases in the approval flow may bypass detection.\n\u003e **Do not rely on this plugin as your sole safety net for critical operations.**\n\nA [Hermes Agent](https://github.com/NousResearch/hermes-agent) plugin that adds custom dangerous command patterns to Hermes's built-in approval system.\n\n## What It Does\n\nHermes ships with ~47 hardcoded dangerous command patterns (`rm -rf`, `git reset --hard`, `docker stop`, etc.). When a command matches, you get an interactive approval prompt: `[o]nce`, `[s]ession`, `[a]lways`, or `[d]eny`.\n\nThis plugin lets you define **your own patterns** in a YAML config file. They get the exact same approval flow — same prompts, same session persistence, same permanent allowlist, same gateway `/approve` and `/deny` support.\n\n**Use cases:**\n- Guard cloud CLI tools (`vultr`, `gcloud`, `aws`, `az`)\n- Protect deployment scripts (`cap deploy`, `fab deploy`)\n- Block dangerous database operations (`DROP TABLE`, `mongodump --drop`)\n- Gate any command that should require explicit human approval\n\n## Installation\n\n### Recommended: Install via Hermes CLI\n\n```bash\nhermes plugins install scross01/hermes-custom-dangerous-patterns-plugin\nhermes plugins enable custom-dangerous-patterns\n```\n\nThe `install` command clones the repo into `~/.hermes/plugins/custom-dangerous-patterns/`\nand prompts to enable it. Use `--enable` to skip the prompt:\n\n```bash\nhermes plugins install scross01/hermes-custom-dangerous-patterns-plugin --enable\n```\n\n### Updating\n\n```bash\nhermes plugins update custom-dangerous-patterns\n```\n\nThen restart Hermes for the changes to take effect.\n\n### Alternative: Manual clone or symlink\n\n```bash\ngit clone https://github.com/scross01/hermes-custom-dangerous-patterns-plugin.git \\\n    ~/.hermes/plugins/custom-dangerous-patterns\n```\n\nOr if you already have the source elsewhere:\n\n```bash\nln -s /path/to/hermes-custom-dangerous-patterns-plugin \\\n      ~/.hermes/plugins/custom-dangerous-patterns\n```\n\n**Important:** The directory inside `~/.hermes/plugins/` must be named `custom-dangerous-patterns`\n(with the trailing `s`).\n\nThen enable:\n\n```bash\nhermes plugins enable custom-dangerous-patterns\n```\n\n### Step 2: Create the config\n\nEasiest — use the interactive bootstrap:\n\n```bash\nhermes custom-dangerous-patterns init --with-examples\n```\n\nThis creates `~/.hermes/custom-dangerous-patterns/` (a directory) with:\n- `00-test.yaml` — safe `[TEST]` patterns (all disabled)\n- `01-examples.yaml` — fully-enabled example patterns (only with `--with-examples`)\n\nWithout `--with-examples`, creates a minimal config directory with safe test patterns (all disabled).\n\nOr create `~/.hermes/custom-dangerous-patterns/` manually — see [Configuration](#configuration).\n\n\u003e **Note:** Directory mode is the **preferred** configuration setup.\n\u003e The plugin also supports a single `custom-dangerous-patterns.yaml` file\n\u003e or *combined mode* where both the directory and sibling `.yaml` file are\n\u003e loaded and merged together.\n\n### Step 3: Restart Hermes\n\nThe plugin loads at startup. Restart the gateway or start a new CLI session:\n\n```bash\nhermes gateway restart    # if using the gateway\n# or just start a new `hermes` CLI session\n```\n\n### Step 4: Test it\n\nTest your patterns without running real commands:\n\n```bash\nhermes custom-dangerous-patterns test \"vultr instance delete --instance-id cb670a12\"\n```\n\nThen try it live:\n\n```\n\u003e vultr instance delete --instance-id cb670a12-e4f5-6d78-ab90-1234567890ab\n\n⚠️ Dangerous command detected: Vultr destructive instance/snapshot command\n    vultr instance delete --instance-id cb670a12-e4f5-6d78-ab90-1234567890ab\n\n  [o]nce    — allow this one time\n  [s]ession — allow for this session\n  [a]lways  — always allow this pattern\n  [d]eny    — block (default)\n```\n\n## Configuration\n\n### Config Location\n\n**Directory (preferred):**\n\n```\n~/.hermes/custom-dangerous-patterns/\n```\n\nAll `*.yaml` files in the directory are loaded and merged alphabetically.\nMost CLI write commands (`enable`, `disable`, `add` without `--target`)\nwrite delta entries to `99-custom.yaml` — user-created files are never\nmodified.\n\nTwo exceptions:\n- **`remove`** deletes entries directly from source YAML files\n- **`add --target \u003cfilename\u003e`** writes to the specified file\n\n**Single file (fallback):**\n\n```\n~/.hermes/custom-dangerous-patterns.yaml\n```\n\n**Combined mode:** When both the directory and the sibling `.yaml` file\nexist, both are loaded and merged (directory files take precedence via\ndedup).\n\nOverride with env var:\n\n```bash\nexport HERMES_CUSTOM_PATTERNS_PATH=/path/to/config.yaml\n\n# Or point to a directory:\nexport HERMES_CUSTOM_PATTERNS_PATH=/path/to/config-directory/\n```\n\n### Block Patterns\n\nThese commands trigger the approval prompt:\n\n```yaml\npatterns:\n  - pattern: '\\bvultr\\b'\n    description: 'Vultr CLI command'\n    enabled: true\n    group: cloud\n    protected: false\n    examples:\n      - 'vultr account info'\n      - 'vultr instance list'\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `pattern` | Yes* | Python regex (matched with `re.IGNORECASE \\| re.DOTALL`). Can be omitted if `glob` is provided — the regex is auto-generated from the glob on config load. |\n| `description` | Yes | Human-readable label shown in the approval prompt |\n| `examples` | No | Documentation-only list of example commands |\n| `enabled` | No | Boolean (default `true`). Set `false` to temporarily disable a pattern |\n| `group` | No | Optional string tag for categorization (e.g., `cloud`, `database`, `testing`) |\n| `protected` | No | Boolean (default `false`). If `true`, the pattern's regex is integrity-checked across sessions |\n| `glob` | No | Original glob string saved when pattern was created via `--glob`. If `pattern` is not present, the glob is auto-converted to regex on config load. |\n\n\u003e **\\* `pattern` or `glob` required.** At least one must be present. If both are provided, `pattern` is used as-is. If only `glob` is present, the regex is auto-generated during config validation.\n\n### Deny Patterns\n\nCommands matching deny patterns are **blocked immediately without an approval prompt**. They are checked **before** allow and block patterns — deny wraps the original guard function and intercepts first. Useful for commands that should *never* be run without manual config changes.\n\n```yaml\ndeny_patterns:\n  - pattern: '\\bgit\\s+push\\s+--force\\b'\n    description: 'Force git push'\n    enabled: true\n    group: git\n    examples:\n      - 'git push --force origin main'\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `pattern` | Yes* | Python regex (same flags as block patterns). Can be omitted if `glob` is provided — auto-generated from glob. |\n| `description` | Yes | Human-readable label shown in the block message |\n| `examples` | No | Documentation-only list of example commands |\n| `enabled` | No | Boolean (default `true`). Set `false` to temporarily disable |\n| `group` | No | Optional string tag for categorization |\n| `protected` | No | Boolean (default `false`). If `true`, integrity-checked across sessions |\n| `glob` | No | Original glob string. If `pattern` is absent, auto-converted to regex on load. |\n\n\u003e **\\* `pattern` or `glob` required.** At least one must be present. If both are provided, `pattern` is used as-is.\n\n**Behavior note:** Deny patterns are checked by a wrapper around `check_all_command_guards()` that runs before `--yolo`/`mode=off` are evaluated. This means `--yolo` does **not** bypass deny patterns — an intentional safeguard that ensures deny-gated commands are always blocked regardless of mode. A future Hermes core integration (v0.5.0) may add native deny-pattern support upstream, at which point this workaround can be removed.\n\n### Allow Patterns\n\nExempt specific commands from approval, even if they match a block pattern:\n\n```yaml\nallow_patterns:\n  - pattern: '\\bvultr\\s+(account\\s+info|instance\\s+list)\\b'\n    description: 'Read-only Vultr commands'\n    enabled: true\n    group: cloud\n```\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `pattern` | Yes* | Python regex (same flags as block patterns). Can be omitted if `glob` is provided — auto-generated from glob. |\n| `description` | No | Documentation-only label |\n| `enabled` | No | Boolean (default `true`). Set `false` to temporarily disable |\n| `group` | No | Optional string tag for categorization |\n| `protected` | No | Boolean (default `false`). If `true`, integrity-checked across sessions |\n| `glob` | No | Original glob string. If `pattern` is absent, auto-converted to regex on load. |\n\n\u003e **\\* `pattern` or `glob` required.** At least one must be present. If both are provided, `pattern` is used as-is.\n\n### A Note on `\\b` (Word Boundaries)\n\nPatterns use `\\b` to match whole words only. This prevents false positives where a command name appears as a substring:\n\n| Pattern | Matches | Doesn't match |\n|---------|---------|---------------|\n| `\\bvultr\\b` | `vultr instance list` | `echo vultr_test`, `my-vultr-server` |\n| `\\baws\\s+ec2\\b` | `aws ec2 describe-instances` | `aws-ec2-tool`, `paws ec2` |\n| `\\bterraform destroy\\b` | `terraform destroy -auto-approve` | `echo \"terraform destroy\"` in a script |\n\nWithout `\\b`, `\\bvultr` would match any string containing \"vultr\" — including hostnames, variable names, or unrelated commands. The `\\b` anchor ensures the pattern only triggers on the actual CLI tool name.\n\n**Tip:** Use single-quoted YAML strings for patterns — backslashes pass through literally (`'\\bvultr\\b'`), avoiding the double-escaping needed with double quotes (`\"\\\\bvultr\\\\b\"`).\n\n### Evaluation Order\n\n\u003e **Note:** The runtime evaluation order differs from the logical order because the deny-pattern wrapper runs *before* the original `check_all_command_guards()` function that contains the yolo/mode=off check. This means deny patterns intercept `--yolo` and `mode=off`.\n\nEach check is tagged with its source:\n- `[Plugin]` — this plugin's custom checks\n- `[Hermes]` — Hermes Agent's built-in checks\n\n```\n 1. [Plugin]  Deny patterns (custom)        → BLOCKED immediately, no prompt\n 2. [Hermes]  Hardline check                → blocked unconditionally\n 3. [Hermes]  Sudo stdin guard              → blocked unconditionally\n 4. [Hermes]  Yolo / mode=off               → bypasses steps 5-7\n 5. [Plugin]  Allow patterns (custom)       → command runs, no prompt (allow wins)\n 6. detect_dangerous_command():             — same approval prompt for both —\n    a. [Plugin]  Block patterns (custom)    → [o]nce/[s]ession/[a]lways/[d]eny\n    b. [Hermes]  Built-in patterns          → [o]nce/[s]ession/[a]lways/[d]eny\n 7. [Hermes]  Tirith security scan          → approval prompt if findings\n```\n\n**What each tier means:**\n\n| Tier | Source | Behavior | Prompt? | Bypassed by `--yolo`? |\n|------|--------|----------|---------|----------------------|\n| Deny patterns | Plugin | **Immediate block** — command is rejected before any approval logic runs | ❌ No | ❌ No |\n| Hardline / Sudo | Hermes | **Unconditional block** — catastrophic or dangerous-by-design commands | ❌ No | ❌ No |\n| Allow patterns | Plugin | **Silent pass** — command runs without any check (allow wins over block) | ❌ No | N/A |\n| Block patterns | Plugin | **Approval prompt** — same as built-in DANGEROUS_PATTERNS | ✅ Yes | ✅ Yes |\n| Built-in patterns | Hermes | **Approval prompt** — Hermes's ~47 hardcoded dangerous command patterns | ✅ Yes | ✅ Yes |\n| Tirith scan | Hermes | **Approval prompt** — security scan of command content | ✅ Yes | ✅ Yes |\n\n**Key rules:**\n- **Allow wins over block.** If a command matches both an allow pattern and a block pattern, allow wins and no prompt is shown.\n- **Deny wins over allow.** Deny patterns are checked before allow patterns. If a command matches a deny pattern, it is blocked before allow patterns are even evaluated.\n- **Deny is immediate-block; block is approval-prompt.** Block patterns and built-in patterns both go through the same `detect_dangerous_command()` approval flow. Deny patterns skip it entirely.\n- **Deny bypasses yolo.** Deny patterns are evaluated outside the original guard function, so `--yolo` does not bypass them.\n\n### Config Integrity \u0026 Protected Patterns\n\nThe plugin tracks the integrity of your configuration across sessions:\n\n- **Config hash tracking:** A SHA-256 hash of your full config YAML is stored in `~/.hermes/.custom-patterns-hash`. If the config changes between sessions, a `WARNING` is logged with the old and new pattern counts.\n- **Protected patterns:** Patterns with `protected: true` have their individual regex SHA-256 hashed and tracked. If a protected pattern is **modified** or **removed**, a `CRITICAL` security warning is logged at startup.\n- **Allow shadowing detection:** When an allow pattern could bypass a built-in dangerous pattern without a corresponding custom block pattern, a `WARNING` is logged with the details.\n\nThese integrity checks provide defense-in-depth against unauthorized config tampering, but they are **detective, not preventive** — the plugin detects and logs changes but does not prevent them. See [Security \u0026 Risks](#security--risks) for more on the trust model.\n\n### Directory Config Loading\n\nInstead of a single file, you can use a **directory**. The plugin loads all `*.yaml` files in alphabetical order and merges them:\n\n- Lists (`patterns`, `allow_patterns`, `deny_patterns`) are **extended** (appended)\n- Scalars override previous values\n\nThis is useful for splitting configs by tool or team:\n\n```bash\n~/.hermes/custom-dangerous-patterns/\n├── 10-cloud.yaml       # cloud CLI patterns\n├── 20-database.yaml     # database patterns\n└── 30-deployment.yaml   # deploy tool patterns\n```\n\nUse `hermes custom-dangerous-patterns init` to create a config directory\nwith starter files, or set the directory path via `$HERMES_CUSTOM_PATTERNS_PATH`.\n\n### Full Example\n\n```yaml\n# ~/.hermes/custom-dangerous-patterns.yaml\n#\n# TIP: Use single-quoted strings for patterns — backslashes pass through\n# literally:  '\\bvultr\\b'  not  \"\\\\bvultr\\\\b\"\n\npatterns:\n  # ── Cloud CLI tools (destructive) ────────────────────────────────\n  - pattern: '\\bvultr\\s+(instance\\s+create|instance\\s+delete|snapshot\\s+create|snapshot\\s+delete)\\b'\n    description: 'Vultr destructive instance/snapshot command'\n    examples:\n      - 'vultr instance delete --instance-id cb670a12-e4f5-6d78-ab90-1234567890ab'\n      - 'vultr snapshot delete --snapshot-id 5a3b2c1d'\n\n  - pattern: '\\bterraform\\s+(destroy|apply)\\b'\n    description: 'Terraform destroy/apply (infrastructure mutation)'\n    examples:\n      - 'terraform destroy -auto-approve'\n      - 'terraform apply -auto-approve'\n\n  - pattern: '\\baws\\s+(ec2|s3|rds|iam|lambda|cloudformation)\\b'\n    description: 'AWS CLI mutating service command'\n    examples:\n      - 'aws ec2 terminate-instances --instance-ids i-12345'\n      - 'aws s3 rb s://my-bucket --force'\n      - 'aws rds delete-db-instance --db-instance-identifier mydb'\n\n  - pattern: '\\bgcloud\\s+(compute\\s+instances\\s+delete|projects\\s+delete)\\b'\n    description: 'GCP destructive command'\n    examples:\n      - 'gcloud compute instances delete my-vm --zone=us-central1-a'\n\n  - pattern: '\\boci\\s+(compute\\s+instance\\s+terminate|database\\s+db\\s+system\\s+delete|network\\s+vcn\\s+delete)\\b'\n    description: 'Oracle Cloud destructive command'\n    examples:\n      - 'oci compute instance terminate --instance-id ocid1.instance.oc1..aaaaaaaa'\n      - 'oci database db-system delete --db-system-id ocid1.dbsystem.oc1..aaaaaaaa'\n\n  - pattern: '\\bdoctl\\s+(compute\\s+droplet\\s+delete|kubernetes\\s+cluster\\s+delete|databases\\s+delete)\\b'\n    description: 'DigitalOcean destructive command'\n    examples:\n      - 'doctl compute droplet delete 12345678'\n      - 'doctl kubernetes cluster delete my-cluster'\n\n  - pattern: '\\bkubectl\\s+delete\\s+namespace\\b'\n    description: 'Kubernetes namespace deletion'\n    examples:\n      - 'kubectl delete namespace staging'\n\n  # ── Deployment tools ─────────────────────────────────────────────\n  - pattern: '\\bcap\\s+\\w+\\s+deploy\\b'\n    description: 'Capistrano production deploy'\n    examples:\n      - 'cap production deploy'\n\n  - pattern: '\\bfab\\s+\\w*\\s*deploy\\b'\n    description: 'Fabric deploy'\n    examples:\n      - 'fab deploy production'\n\n  # ── Database operations ──────────────────────────────────────────\n  - pattern: '\\bDROP\\s+(TABLE|DATABASE)\\b'\n    description: 'SQL DROP statement'\n    examples:\n      - 'DROP TABLE users'\n      - 'DROP DATABASE production'\n\n  - pattern: '\\bmongodump\\b.*--drop\\b'\n    description: 'MongoDB dump with --drop (overwrites existing data)'\n    examples:\n      - 'mongodump --drop --db production'\n\n# ── Allow patterns ────────────────────────────────────────────────\n# Commands matching these are EXEMPT from approval, even if they\n# also match a blocked pattern. Evaluated BEFORE block patterns.\n# Allow wins over block.\n\nallow_patterns:\n  # ── Read-only cloud commands (safe) ─────────────────────────────\n  - pattern: '\\bvultr\\s+(account\\s+info|instance\\s+list|dns\\s+list|plan\\s+list)\\b'\n    description: 'Read-only Vultr commands'\n\n  - pattern: '\\baws\\s+(ec2\\s+describe|s3\\s+ls|s3\\s+cp.*--dry-run|iam\\s+list)\\b'\n    description: 'AWS read-only commands'\n\n  - pattern: '\\bterraform\\s+(plan|state\\s+list|output)\\b'\n    description: 'Terraform read-only commands'\n\n  - pattern: '\\boci\\s+(compute\\s+instance\\s+list|network\\s+vcn\\s+list|database\\s+db\\s+system\\s+list)\\b'\n    description: 'Oracle Cloud read-only commands'\n\n  - pattern: '\\bdoctl\\s+(compute\\s+droplet\\s+list|kubernetes\\s+cluster\\s+list|databases\\s+list)\\b'\n    description: 'DigitalOcean read-only commands'\n\n  # ── Help and utility (safe) ─────────────────────────────────────\n  - pattern: '\\b(vultr|gcloud|aws|terraform|kubectl|oci|doctl)\\s+(-h|--help|help)\\b'\n    description: 'Help flags are safe'\n\n  - pattern: '\\b(vultr|gcloud|aws|terraform|oci|doctl)\\s+completion\\b'\n    description: 'Shell completion scripts are safe'\n```\n\n## CLI Reference\n\nAll commands follow the `hermes custom-dangerous-patterns \u003cverb\u003e` pattern, consistent with other Hermes subcommands like `hermes plugins`.\n\n### `list` — Show your patterns\n\n```bash\nhermes custom-dangerous-patterns list                    # all patterns\nhermes custom-dangerous-patterns list --type block       # block patterns only\nhermes custom-dangerous-patterns list --type allow       # allow patterns only\nhermes custom-dangerous-patterns list --type deny        # deny patterns only\nhermes custom-dangerous-patterns list --group cloud      # patterns in a group\nhermes custom-dangerous-patterns list --disabled         # only disabled patterns\nhermes custom-dangerous-patterns list --enabled          # only active patterns\nhermes custom-dangerous-patterns list --search aws       # search descriptions and patterns\nhermes custom-dangerous-patterns list --builtins         # include Hermes built-in patterns (snapshot)\n```\n\n\u003e **Note:** `--builtins` uses a static snapshot of Hermes's built-in patterns\n\u003e bundled at plugin install time. These may drift from Hermes core updates.\n\n### `test \u003ccommand\u003e` — Verify patterns before running\n\nTest a command against all patterns to see what would happen **without running it**.\n\n```bash\nhermes custom-dangerous-patterns test \"vultr instance delete\"\nhermes custom-dangerous-patterns test \"vultr account info\" --verbose\nhermes custom-dangerous-patterns test \"git push --force\" --skip-builtins\n```\n\nShows which patterns match and the result: **DENY** (blocked immediately), **ALLOW** (runs freely), **APPROVAL PROMPT** (interactive prompt), or **PASS** (no patterns matched).\n\n`--verbose` shows full pattern regex and built-in matches. `--skip-builtins` omits Hermes's ~47 built-in patterns to focus on custom patterns.\n\n### `init` — First-run bootstrap\n\n```bash\nhermes custom-dangerous-patterns init                    # minimal config with safe [TEST] patterns (all disabled)\nhermes custom-dangerous-patterns init --with-examples    # full example config (all enabled for demonstration)\nhermes custom-dangerous-patterns init --force            # overwrite existing config without prompting\n```\n\n### `enable / disable` — Toggle patterns\n\nToggle patterns on/off without editing YAML. Target by index, description substring, or group.\n\n```bash\nhermes custom-dangerous-patterns enable 1                          # by index (from list output)\nhermes custom-dangerous-patterns disable \"Vultr\"                    # by description substring\nhermes custom-dangerous-patterns enable --group cloud               # all patterns in a group\nhermes custom-dangerous-patterns enable --group testing --dry-run   # preview without saving\n```\n\nWith no target or group specified, `enable` and `disable` launch\ninteractive selection automatically.\n\nAfter any write command, the CLI reminds you to restart Hermes for changes to take effect.\n\n### `validate` — Check config syntax\n\n```bash\nhermes custom-dangerous-patterns validate                    # validate default config\nhermes custom-dangerous-patterns validate --path /tmp/cfg.yaml  # validate a specific file\nhermes custom-dangerous-patterns validate --quiet            # exit code only (CI/CD)\n```\n\nValidates YAML syntax, regex compilation, and pattern consistency. In\naddition to basic validation, if a pattern defines both `glob` and\n`pattern` and the stored regex differs from what the glob would generate,\na warning is emitted to flag the discrepancy.\n\nExit code 0 = valid, 1 = errors found, 2 = file not found.\n\n### `info` — State dashboard\n\nShows config path, pattern counts by type, integrity status, protected patterns, and group breakdown.\n\n```bash\nhermes custom-dangerous-patterns info\n```\n\n### `logs` — Extract plugin log entries\n\n```bash\nhermes custom-dangerous-patterns logs                          # all plugin log entries\nhermes custom-dangerous-patterns logs --level WARNING          # filter by minimum level\nhermes custom-dangerous-patterns logs --limit 20               # last 20 entries\nhermes custom-dangerous-patterns logs --since 2026-06-01       # entries since a date\nhermes custom-dangerous-patterns logs --follow                 # tail the log (Ctrl+C to exit)\n```\n\n### `add` — Add a pattern\n\nInteractive guided prompts or CLI flags for scripting.\n\n```bash\n# Interactive (guided prompts for each field, with glob-to-regex support)\nhermes custom-dangerous-patterns add\n\n# Write to a specific file in the config directory\nhermes custom-dangerous-patterns add --target 02-mycloud.yaml --type block \\\n    --pattern '\\bheroku\\s+(apps:destroy|pg:reset)\\b' \\\n    --description 'Heroku destructive commands' \\\n    --group cloud\n\n# Glob-style pattern entry (converted to regex automatically).\n# * matches ONE word, ** matches ANYTHING, {a,b} for alternatives.\nhermes custom-dangerous-patterns add --type block \\\n    --glob 'heroku *destroy*' \\\n    --description 'Heroku destructive commands'\n\n# Non-interactive (full CLI flags)\nhermes custom-dangerous-patterns add --type block \\\n    --pattern '\\bheroku\\s+(apps:destroy|pg:reset)\\b' \\\n    --description 'Heroku destructive commands' \\\n    --group cloud\n```\n\n| Flag | Description |\n|------|-------------|\n| `-t` / `--type` | Pattern type: `block`, `allow`, or `deny` (required non-interactive) |\n| `-p` / `--pattern` | Raw regex pattern (required non-interactive; mutually exclusive with `--glob`) |\n| `--glob` | Glob-style pattern like `echo hello` — converted to regex automatically |\n| `-d` / `--description` | Human-readable description |\n| `-g` / `--group` | Optional group tag for categorization |\n| `--examples` | One or more example commands |\n| `--disabled` | Add as disabled (default: enabled) |\n| `--protected` | Mark as protected (integrity tracked across sessions) |\n| `--dry-run` | Preview without saving |\n| `--target FILENAME` | Write to a specific `.yaml` file in the config directory (requires directory mode) |\n\n\u003e **Note:** `--pattern` and `--glob` are mutually exclusive. Without any\n\u003e flags, `add` launches interactive mode with guided prompts and\n\u003e glob-to-regex conversion.\n\n### `remove` — Remove a pattern\n\n```bash\n# Interactive (shows numbered list)\nhermes custom-dangerous-patterns remove\n\n# By index (from `list` output)\nhermes custom-dangerous-patterns remove 3\n\n# By description substring\nhermes custom-dangerous-patterns remove \"Heroku\"\n\n# Force removal without confirmation prompt\nhermes custom-dangerous-patterns remove 3 --force\n\n# Preview without deleting\nhermes custom-dangerous-patterns remove 7 --dry-run\n```\n\n| Flag | Description |\n|------|-------------|\n| `target` | Pattern index (from `list`) or description substring |\n| `-t` / `--type` | Filter by type: `block`, `allow`, or `deny` |\n| `--force` | Skip confirmation prompt |\n| `--dry-run` | Preview without deleting |\n\nUnlike `enable`/`disable` (which write delta entries to `99-custom.yaml`),\n**`remove` truly deletes the pattern** from the source YAML file — the\nlines are removed, no remnant written.\n\nProtected patterns cannot be removed via CLI; edit the config file\ndirectly to remove them.\n\n---\n\n## How It Works\n\nThe plugin injects your custom patterns into Hermes's `DANGEROUS_PATTERNS` list at startup via pattern injection + two monkey-patches:\n\n1. **`detect_dangerous_command()`** — patched for allow-pattern support (allow patterns bypass all detection)\n2. **`check_all_command_guards()`** — patched for deny-pattern support (deny patterns block immediately, no prompt)\n\n```\nHermes startup:\n  1. Plugin discovery → register(ctx) runs\n  2. Resolves config path (env var → ~/.hermes/custom-dangerous-patterns/ directory or single .yaml file)\n  3. Loads YAML (supports directory mode: all *.yaml files merged)\n  4. Runs integrity checks (config SHA-256 hash, protected pattern verification)\n  5. Compiles regex patterns (block, allow, deny)\n  6. Appends block patterns to DANGEROUS_PATTERNS / DANGEROUS_PATTERNS_COMPILED\n  7. Monkey-patches detect_dangerous_command() for allow-pattern support\n  8. Monkey-patches check_all_command_guards() for deny-pattern support\n  9. Checks for allow shadowing (allow patterns that may bypass built-in patterns)\n  10. Agent runs → allow/deny/block patterns checked in order → approval flow\n```\n\nThe built-in approval system then handles everything automatically:\n\n| Context | Behavior |\n|---------|----------|\n| **CLI** | Interactive `[o]nce`/`[s]ession`/`[a]lways`/`[d]eny` prompt |\n| **Gateway** (Telegram/Discord/etc.) | `/approve` and `/deny` commands, async approval queue |\n| **Session persistence** | \"Session\" choice survives for the session duration |\n| **Permanent allowlist** | \"Always\" choice persists to `command_allowlist` in `config.yaml` |\n| **Smart mode** | If `approvals.mode: smart`, auxiliary LLM assesses custom patterns |\n| **Cron** | Respects `approvals.cron_mode` (deny by default) |\n| **`--yolo`** | Block patterns (custom + built-in) are bypassed. **Deny patterns still block** — they intercept before the yolo check. |\n\n## Edge Cases\n\n| Scenario | Behavior |\n|----------|----------|\n| Config file missing | Plugin loads silently, no patterns injected |\n| Config file invalid YAML | Log WARNING, plugin loads with empty pattern list |\n| Invalid regex in pattern | Log WARNING for that pattern, skip it, load valid ones |\n| Block pattern matches but allow also matches | Allow wins — no prompt (allow wins over block) |\n| Deny pattern matches (and allow also matches) | Deny wins — blocked immediately (deny checked before allow) |\n| Deny pattern match | Blocked immediately, no prompt |\n| `--yolo` mode | Block patterns (custom + built-in) bypassed. Deny patterns still block — checked outside the original guard function. |\n| `approvals.mode: off` | Block patterns bypassed. Deny patterns still block — checked outside the original guard function. |\n| `approvals.mode: smart` | Custom patterns assessed by auxiliary LLM |\n| Cron session + `cron_mode: deny` | Custom patterns blocked in cron |\n| Container backend (docker, etc.) | All approval checks skipped (sandboxed) |\n| `command_allowlist` \"always\" choice | Persisted to config.yaml — survives restarts |\n| Config changed since last session | WARNING logged with old/new pattern counts |\n| Protected pattern missing/modified | CRITICAL warning logged at startup |\n| Allow pattern shadows built-in pattern | WARNING logged with details |\n\n## Security \u0026 Risks\n\n\u003e The plugin's stance on self-modification is: **allow it, detect it, log it.**\n\nThe agent running Hermes can read and write `~/.hermes/custom-dangerous-patterns.yaml`. This means an agent could add `allow_patterns: [{pattern: '.*'}]` to bypass all approval checks (except hardline commands, which are always blocked). This is by design — the plugin is a safety net, not a jail.\n\nThe `_config_cache` freeze means mid-session edits are ignored, but changes take effect after the next Hermes restart.\n\n### Risks the plugin cannot prevent\n\n- An agent could add `allow_patterns: [{pattern: '.*'}]` to exempt itself from all dangerous-pattern checks\n- An agent could modify protected patterns — changing both the pattern and its `protected` flag\n- Config modifications via Python I/O or AI tool calls are invisible to pattern matching. Only literal command-line path references to the config file are potentially caught by patterns\n\n### Defenses the plugin does provide\n\n- **Protected patterns:** Patterns with `protected: true` have their regex SHA-256 hashed and tracked in `~/.hermes/.custom-patterns-hash`. If a protected pattern is modified or removed, a **CRITICAL** security warning is logged at startup.\n- **Config hash tracking:** The full config SHA-256 is stored between sessions. Any change triggers a `WARNING` on next load with details of what changed (old vs new pattern counts).\n- **New-allow shadowing detection:** If a new allow pattern could bypass a built-in dangerous-pattern check without a corresponding custom block pattern, a `WARNING` is logged with details.\n\n### Example bypass vectors\n\n| Command | Why pattern matching doesn't see it |\n|---------|-----------------------------------|\n| `python -c \"open('~/.hermes/custom-dangerous-patterns.yaml').write('...')\"` | Filename is in a Python string, not shell-visible |\n| AI file-write tool call | Tool handles I/O; filename not in command string |\n| `sed -i 's/block/allow/' ~/.hermes/custom-dangerous-patterns.yaml` | Filename visible but not in `_SENSITIVE_WRITE_TARGET` (out of scope) |\n| `tee ~/.hermes/custom-dangerous-patterns.yaml \u003c\u003c 'EOF'` | Same: not in `_SENSITIVE_WRITE_TARGET` (out of scope) |\n\n### User-level hardening options (optional, not default)\n\n- Run the agent and Hermes under **separate OS users** so the agent cannot write to `~/.hermes/custom-dangerous-patterns.yaml` or `~/.hermes/config.yaml`\n- Set config file permissions to `0444` (read-only) for the agent's user\n- Mount the config directory read-only in containerized setups\n- Use `command_allowlist` only for patterns the user personally approved\n\n## Troubleshooting\n\n### Plugin not loading\n\nCheck that the plugin is enabled:\n\n```bash\nhermes plugins list | grep custom-dangerous-patterns\n```\n\nIf not listed, enable it:\n\n```bash\nhermes plugins enable custom-dangerous-patterns\n```\n\n### Patterns not triggering approval\n\n1. Verify the plugin loaded and see active patterns:\n   ```bash\n   hermes custom-dangerous-patterns list\n   ```\n\n2. Test a command against your patterns:\n   ```bash\n   hermes custom-dangerous-patterns test \"vultr instance delete\"\n   ```\n\n3. Check the plugin logs for errors:\n   ```bash\n   hermes custom-dangerous-patterns logs\n   ```\n\n4. Ensure you restarted Hermes after enabling the plugin or changing config.\n\n5. Validate your config syntax:\n   ```bash\n   hermes custom-dangerous-patterns validate\n   ```\n\n### Allow patterns not working\n\nAllow patterns are checked **before** block patterns. If a command matches both, the allow wins. Test your pattern matching:\n\n```bash\nhermes custom-dangerous-patterns test \"vultr account info\" --verbose\n```\n\nThe `--verbose` output shows which patterns matched and the result.\n\n### Deny patterns not blocking\n\nIf deny patterns are not blocking commands, verify:\n\n1. The pattern is enabled — `hermes custom-dangerous-patterns list --enabled --type deny`\n2. No allow pattern is intercepting the command before the deny check (allow is checked after deny, so if both match, deny wins)\n3. Restart Hermes after config changes (mid-session edits are silently ignored)\n\nTest deny pattern matching:\n\n```bash\nhermes custom-dangerous-patterns test \"git push --force origin main\"\n```\n\n### Integrity warnings on startup\n\nIf you see `CONFIG CHANGED` or `PROTECTED PATTERN MISSING/MODIFIED` warnings on startup:\n\n1. Review the recent changes to `~/.hermes/custom-dangerous-patterns.yaml`\n2. If the changes were intentional, the warning is informational — no action needed\n3. If the changes were unexpected, investigate who/what modified the config\n\nThe integrity hash file is stored at `~/.hermes/.custom-patterns-hash`. Deleting it will clear the stored hash and suppress warnings until the next config change.\n\n### Config file not found\n\nThe plugin looks for `~/.hermes/custom-dangerous-patterns/` (directory)\nor `~/.hermes/custom-dangerous-patterns.yaml` (single file). Override with:\n\n```bash\nexport HERMES_CUSTOM_PATTERNS_PATH=/path/to/config.yaml\n\n# Or point to a directory:\nexport HERMES_CUSTOM_PATTERNS_PATH=/path/to/config-directory/\n```\n\nSee [Directory Config Loading](#directory-config-loading) for details.\n\n## Project Structure\n\n```\nhermes-custom-dangerous-patterns-plugin/\n├── plugin.yaml          # Hermes plugin manifest\n├── __init__.py          # register(ctx) — injects patterns, monkey-patches detection\n├── config.py            # YAML loading, validation, caching, integrity checks, save_config()\n├── patterns.py          # Pattern compilation and matching (block, allow, deny)\n├── cli.py               # CLI command handlers (hermes custom-dangerous-patterns ...)\n├── logs.py              # Log extraction and filtering for hermes custom-dangerous-patterns logs\n├── AGENTS.md            # Developer guide: gotchas, testing safety, CLI architecture\n├── examples/\n│   ├── 01-examples.yaml                 # Example config with cloud/deployment patterns\n│   └── 00-test.yaml                     # Safe, disabled-by-default test patterns\n├── tests/\n│   ├── conftest.py       # Test fixtures, mocks, helpers\n│   ├── test_config.py    # Config loading, validation, integrity tests\n│   ├── test_patterns.py  # Pattern compilation and matching tests\n│   ├── test_init.py      # Plugin registration and monkey-patch tests\n│   └── test_cli.py       # CLI command handler tests\n├── README.md            # This file\n├── LICENSE              # MIT\n└── .gitignore\n```\n\n## Requirements\n\n- Python 3.11+\n- [Hermes Agent](https://github.com/NousResearch/hermes-agent) (tested with 0.15.1)\n- ruamel.yaml — for config loading and write-back (declared in `plugin.yaml`; Hermes installs it automatically)\n\n### Development\n\n```bash\ngit clone https://github.com/scross01/hermes-custom-dangerous-patterns-plugin.git\ncd hermes-custom-dangerous-patterns-plugin\nuv venv --python 3.11 .venv\nuv sync --extra dev\n```\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscross01%2Fhermes-custom-dangerous-patterns-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscross01%2Fhermes-custom-dangerous-patterns-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscross01%2Fhermes-custom-dangerous-patterns-plugin/lists"}