Back to skill

Security audit

ssh-executor

Security checks for vulnerabilities and agentic risk

Overview

This SSH skill has a coherent purpose, but it needs review because its private-key and sudo-password handling can expose credentials or enable command injection.

Install only if you are comfortable reviewing and hardening the scripts first. Prefer the base key-only edition, avoid password and sudo modes unless necessary, do not export private keys into environment variables, pin dependencies, and treat vault-backed key storage and sudo execution as high-risk until the argument-exposure and command-injection issues are fixed.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (6)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ssh-run.sh:124
Finding

Local Command Injection Through Unsafe Evaluation of SSH Configuration Values

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ssh-run-native.sh:378
Finding

OpenSSH Option Injection Through an Unvalidated Target Argument

Content
View full analysis
"$RESOLVED_FILE" 2>/dev/null RESOLVE_EXIT=$? $SSH_BIN "${SSH_ARGS[@]}" "$TARGET" "$REMOTE_COMMAND" >"$STDOUT_FILE" 2>"$STDERR_FILE" EXIT_CODE=$? set -e ``` ### Technical Analysis The host and optional username are concatenated into `TARGET` and passed directly to OpenSSH. The implementation does not reject a target beginning with `-` and does not otherwise enforce valid hostname or username syntax. OpenSSH treats arguments beginning with `-` as options while it is still processing command-line options. A crafted host can therefore inject SSH options rather than being interpreted as a destination. Particularly dangerous options include proxy-related configuration capable of launching a local helper process. Array-based invocation prevents ordinary shell metacharacter expansion, but it does not prevent option injection into the invoked program. ### Attack Path 1. An attacker supplies or induces the use of a host value beginning with an OpenSSH option prefix. 2. `ssh-run-native.sh` copies this value into `TARGET` without validation. 3. The target is supplied to both the configuration-resolution and connection invocations. 4. OpenSSH interprets the target as an option rather than as a hostname. 5. An injected option causes attacker-selected local behavior, potentially including execution of a local proxy command. 6. The process executes with the Agent's local privil ...[truncated 284 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ssh-keys.sh:93
Finding

Private SSH Key Disclosure Through Vault Resolver Process Arguments

Content
View full analysis
Remediation
View remediation
/cmdline` to ensure key material is absent. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ssh-run-native.sh:351
Finding

Sudo Password Exposure and Remote Shell Injection Through Password Interpolation

Content
View full analysis
' | sudo -S -p '' -- sh -c "$(echo '' | base64 -d)" ENCODED_CMD=$(printf '%s' "$REMOTE_COMMAND" | base64 -w0) REMOTE_COMMAND="echo '${SUDO_PASS}' | sudo -S -p '' -- sh -c \"\$(echo '${ENCODED_CMD}' | base64 -d)\"" ``` The generated command is later passed as an SSH process argument: ```bash $SSH_BIN "${SSH_ARGS[@]}" "$TARGET" "$REMOTE_COMMAND" >"$STDOUT_FILE" 2>"$STDERR_FILE" ``` ### Technical Analysis The sudo password is embedded directly into remote shell source and then included in the local SSH process argument vector. This creates two separate security problems: 1. The password may be visible to local process inspection, auditing, crash-reporting, or monitoring tools. 2. A password containing a single quote or shell syntax can terminate the quoted `echo` argument and alter the remote command. Encoding the requested command does not protect the password because the password itself remains unescaped shell text. The implementation therefore does not satisfy the documented assertion that the password never appears in `ps` output. ### Attack Path **Credential-disclosure path:** 1. The user runs a `--sudo` operation with a password from the vault or environment. 2. The password is interpolated into `REMOTE_COMMAND`. 3. The complete command becomes an argument to the local SSH process. 4. A local process observer captures the SSH argument vector. 5. The observer extracts the sudo password. **Command-injection path:** 1. A compromised or malicious vault backend returns a sudo password containing a quote and shell syntax. 2. The script inserts the value into `echo '${SUDO_PASS ...[truncated 608 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/ssh-client.py:27
Finding

Unpinned Paramiko Installation and User-Writable Import-Path Precedence

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
references/server-to-server-rsync.md:103
Finding

Deprecated Workflow Still Stages a Private SSH Key on a Remote Host

Content
View full analysis
-o StrictHostKeyChecking=yes" \ /path/source/ \ user@:/path/dest/' # 4. Remove the temporary key and verify ssh user@server-a 'shred -u /dev/shm/transfer_key && echo "CLEANUP VERIFIED"' ``` ### Technical Analysis The document clearly labels this pattern as deprecated, dangerous, and a last resort. Nevertheless, it remains an executable workflow available to the Agent and explicitly transfers a private SSH key to another host. Once copied, the key is exposed to administrators, privileged processes, malware, memory inspection, backups, snapshots, and any attacker controlling server A. Cleanup is not atomic and will not occur if the client, network, or remote operation fails before the final step. A tmpfs path reduces persistent storage but does not prevent credential theft while the file exists. This behavior exceeds minimum privilege because client-mediated transfer avoids placing destination credentials on the source host. Agent forwarding is another documented alternative, although it also requires careful trust controls. ### Attack Path 1. The Agent determines that preferred transfer methods are unavailable. 2. With user approval, it copies a private key from the client to server A. 3. The key remains readable on server A during the transfer. 4. A privileged local process or attacker on server A copies the key. 5. Alternatively, interruption occurs before t ...[truncated 502 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (132)

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The example export SSH_KEY="$(cat ~/.ssh/id_rsa)" loads raw private key material into an environment variable, greatly expanding exposure beyond the file itself. Environment variables are commonly inherited by child processes and may be captured by debugging tools, crash reports, agent telemetry, or CI logs, making this a serious credential-handling flaw.

Content

Scanner excerpt · SKILL.md (reported line 62)May include surrounding context.

Claude Code / Codex / Generic LLM

bash
# No vault — use env vars or key files:
export SSH_KEY="$(cat ~/.ssh/id_rsa)"
ssh-run.sh --host my-server --user ubuntu --key ~/.ssh/id_rsa -- 'uptime'

# Or with password (requires SSH_EXECUTOR_ALLOW_DANGEROUS=1):

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 132)May include surrounding context.

md
| `terminal` | Bash scripts (`ssh-run.sh`, `ssh-keys.sh`, `ssh-run-native.sh`) | SSH command execution |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 205)May include surrounding context.

md
| `terminal` | Bash scripts (`ssh-run.sh`, `ssh-keys.sh`, `ssh-run-native.sh`) | SSH command execution |

Chaining Abuse

High
Category
Tool Misuse
Confidence
87% confidence
Finding

The documented pattern chains echo into sudo -S, normalizing shell-pipeline secret injection for privileged execution. Chaining itself is not the core issue, but in this context it compounds credential exposure risk and can make review/auditing of privileged command construction harder.

Content

Scanner excerpt · SKILL.md (reported line 266)May include surrounding context.

md
**Security:**
- Password resolved in RAM, never on disk
- Sent via `echo '<pass>' | sudo -S -p ''` — password never appears on the command line (`ps`)
- `-p ''` suppresses sudo password prompt (avoids stderr pollution)
- Original command is base64-encoded to avoid quote escaping issues
- `--sudo` automatically enables `--confirm-dangerous` (no extra flag needed)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · SKILL.md (reported line 491)May include surrounding context.

md
The skill is split into two editions, built from the same source via `build.sh`:

| Edition | Package | Auth | Sudo | Lines |
|---------|---------|------|------|-------|
| **Base** | `ssh-executor-<ver>.zip` | Key only | No | 270 |
| **Full** | `ssh-executor-full-<ver>.zip` | Key + password | Yes | 481 |

Privileged Container / Container Escape

High
Category
Privilege Escalation
Confidence
85% confidence
Finding

Potential security issue detected. Manual review is recommended.

Content

Scanner excerpt · references/docker-diagnostics-without-cli.md (reported line 38)May include surrounding context.

Compare the process network namespace with the host's:

bash
host_ns=$(readlink /proc/1/ns/net)
container_ns=$(readlink /proc/<PID>/ns/net)
if [ "$host_ns" = "$container_ns" ]; then
  echo "network_mode: host"

Privileged Container / Container Escape

High
Category
Privilege Escalation
Confidence
85% confidence
Finding

Potential security issue detected. Manual review is recommended.

Content

Scanner excerpt · references/docker-diagnostics-without-cli.md (reported line 159)May include surrounding context.

md
Diagnosis performed:
1. `cat /proc/<PID>/cmdline` → confirmed mysqld with MariaDB args
2. `readlink /proc/<PID>/ns/net == readlink /proc/1/ns/net` → network_mode host
3. `ss -tlnp` → **zero** port 3306 on any IP
4. `cat /etc/mysql/mysql.conf.d/mysqld.cnf` → bind-address = 127.0.0.1 on host
   (but this is the host config, not the container's)

Privileged Container / Container Escape

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Potential security issue detected. Manual review is recommended.

Content

Scanner excerpt · references/docker-diagnostics-without-cli.md (reported line 176)May include surrounding context.

md
| Problem | Cause | Solution |
|----------|-------|---------|
| `ls /proc/PID/fd/` empty | PID runs as different UID (e.g. 999 = mysql) | Try `sudo ls` or use other techniques |
| `nsenter` access denied | No CAP_SYS_ADMIN permission | Do not use nsenter without sudo |
| `ip neigh` shows FAILED | Container with network_mode host (no dedicated IP) | Container shares host IP; look for port on host |
| Bridge linkdown but IP configured | Docker network without containers (created but unused) | Check which bridge has REACHABLE/STALE traffic |
| `docker logs` unavailable | No docker CLI access | Only option: `journalctl` or process logs in datadir |

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/safety.md (reported line 33)May include surrounding context.

md
- deletes, rotates, or truncates data (`truncate`, `dd`, logrotate actions)
- changes containers, databases, firewalls, or network state (`docker rm|down|kill`, `kubectl delete`, `iptables`, `ufw`, `firewall-cmd`, `ip link set`, `ip addr add|del`, `nmcli`)
- writes to disk or pipes output to a file (`>`, `>>`, `| tee`, `dd`)
- executes code on the remote host that was not explicitly reviewed (`curl | bash`, `wget -O- | sh`, `eval`, `source`)

**When in doubt, treat the command as dangerous and ask for confirmation.**

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/safety.md (reported line 33)May include surrounding context.

md
- deletes, rotates, or truncates data (`truncate`, `dd`, logrotate actions)
- changes containers, databases, firewalls, or network state (`docker rm|down|kill`, `kubectl delete`, `iptables`, `ufw`, `firewall-cmd`, `ip link set`, `ip addr add|del`, `nmcli`)
- writes to disk or pipes output to a file (`>`, `>>`, `| tee`, `dd`)
- executes code on the remote host that was not explicitly reviewed (`curl | bash`, `wget -O- | sh`, `eval`, `source`)

**When in doubt, treat the command as dangerous and ask for confirmation.**

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · SKILL.md (reported line 386)May include surrounding context.

md
| 2 | Credential Mismanagement | 99% | Header forbids passwords but docs instruct storage | Header clarified: "passwords for automation may be stored in Vaultwarden with explicit approval" |
| 3 | Key Exfiltration | 99% | Rsync workflow copies private key to remote server | server-to-server-rsync.md deprecated; ForwardAgent preferred |
| 4 | Host-Key Bypass | 99% | AutoAddPolicy in Python, accept-new in native | Default RejectPolicy (Python), StrictHostKeyChecking=yes (native), accept-new removed |
| 5 | Destructive Commands | 94% | sudo find ... -delete without confirmation | Warning banner in remote-backup-cleanup.md |
| 6 | Undeclared MCP | 92% | Shell, file, env-var access undeclared | MCP Permissions Declaration section added |

## Findings Fixed in v2.2.1 (Medium Severity)

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · references/security-audit-2026-07-clawhub.md (reported line 15)May include surrounding context.

md
| 2 | Credential Mismanagement | 99% | Header forbids passwords but docs instruct storage | Header clarified: "passwords for automation may be stored in Vaultwarden with explicit approval" |
| 3 | Key Exfiltration | 99% | Rsync workflow copies private key to remote server | server-to-server-rsync.md deprecated; ForwardAgent preferred |
| 4 | Host-Key Bypass | 99% | AutoAddPolicy in Python, accept-new in native | Default RejectPolicy (Python), StrictHostKeyChecking=yes (native), accept-new removed |
| 5 | Destructive Commands | 94% | sudo find ... -delete without confirmation | Warning banner in remote-backup-cleanup.md |
| 6 | Undeclared MCP | 92% | Shell, file, env-var access undeclared | MCP Permissions Declaration section added |

## Findings Fixed in v2.2.1 (Medium Severity)

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · references/security-audit-2026-07-clawhub.md (reported line 24)May include surrounding context.

md
|---|----------|-----------|---------|-----|
| 7 | Temp Key Cleanup | 93-95% | trap EXIT only, kill -9 bypasses | trap EXIT INT TERM HUP + shred -u |
| 8 | restore-to-file Path | 92% | Writes to any caller-specified path | Path validation: rejects /etc, /boot, /sys, /proc, /dev, /run; warns non-tmp |
| 9 | Missing User Warning | — | No warning on --host-key-checking no | Explicit stderr MITM warning |
| 10 | Pass-through Bug | — | --host-key-checking ignored by Python backend | ssh-run.sh now captures and passes to ssh-client.py |
| 11 | SSL/TLS | — | check_hostname=False without caveat | "Only safe on trusted local networks" |

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · references/security-audit-2026-07-clawhub.md (reported line 26)May include surrounding context.

md
| 8 | restore-to-file Path | 92% | Writes to any caller-specified path | Path validation: rejects /etc, /boot, /sys, /proc, /dev, /run; warns non-tmp |
| 9 | Missing User Warning | — | No warning on --host-key-checking no | Explicit stderr MITM warning |
| 10 | Pass-through Bug | — | --host-key-checking ignored by Python backend | ssh-run.sh now captures and passes to ssh-client.py |
| 11 | SSL/TLS | — | check_hostname=False without caveat | "Only safe on trusted local networks" |

## Confirmed Safe (No Action Needed)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/server-to-server-rsync.md (reported line 35)May include surrounding context.

  1. The destination directory is writable by the user on server B:
    bash
    ssh -p <PORT> user@server-b 'touch /path/dest/.test_write && rm /path/dest/.test_write' 2>&1
    
    If it fails (Permission denied):
    • Try sudo mkdir -p /path/dest/ (some servers have NOPASSWD)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/server-to-server-rsync.md (reported line 89)May include surrounding context.

/tmp/staging/ user@server-b:/path/dest/

Clean up staging

rm -rf /tmp/staging

text

⚠️ **Downside:** all traffic passes through the client twice.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/server-to-server-rsync.md (reported line 89)May include surrounding context.

/tmp/staging/ user@server-b:/path/dest/

Clean up staging

rm -rf /tmp/staging

text

⚠️ **Downside:** all traffic passes through the client twice.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 352)May include surrounding context.

md
## 1. UserKnownHostsFile /dev/null Nullifies StrictHostKeyChecking

**Symptom:** `Host key verification failed` (exit 255) even though the host key is in `~/.ssh/known_hosts`.

**Root cause:** `~/.ssh/config` has `UserKnownHostsFile /dev/null` — SSH effectively has no trust store. When our skill sets `StrictHostKeyChecking=yes` (hardening v2.2.0), strict checking fails because there's nothing to check against.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 392)May include surrounding context.

md
## 1. UserKnownHostsFile /dev/null Nullifies StrictHostKeyChecking

**Symptom:** `Host key verification failed` (exit 255) even though the host key is in `~/.ssh/known_hosts`.

**Root cause:** `~/.ssh/config` has `UserKnownHostsFile /dev/null` — SSH effectively has no trust store. When our skill sets `StrictHostKeyChecking=yes` (hardening v2.2.0), strict checking fails because there's nothing to check against.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 393)May include surrounding context.

md
## 1. UserKnownHostsFile /dev/null Nullifies StrictHostKeyChecking

**Symptom:** `Host key verification failed` (exit 255) even though the host key is in `~/.ssh/known_hosts`.

**Root cause:** `~/.ssh/config` has `UserKnownHostsFile /dev/null` — SSH effectively has no trust store. When our skill sets `StrictHostKeyChecking=yes` (hardening v2.2.0), strict checking fails because there's nothing to check against.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/safety.md (reported line 17)May include surrounding context.

md
## 1. UserKnownHostsFile /dev/null Nullifies StrictHostKeyChecking

**Symptom:** `Host key verification failed` (exit 255) even though the host key is in `~/.ssh/known_hosts`.

**Root cause:** `~/.ssh/config` has `UserKnownHostsFile /dev/null` — SSH effectively has no trust store. When our skill sets `StrictHostKeyChecking=yes` (hardening v2.2.0), strict checking fails because there's nothing to check against.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/testing-pitfalls-2026-07-23.md (reported line 7)May include surrounding context.

md
## 1. UserKnownHostsFile /dev/null Nullifies StrictHostKeyChecking

**Symptom:** `Host key verification failed` (exit 255) even though the host key is in `~/.ssh/known_hosts`.

**Root cause:** `~/.ssh/config` has `UserKnownHostsFile /dev/null` — SSH effectively has no trust store. When our skill sets `StrictHostKeyChecking=yes` (hardening v2.2.0), strict checking fails because there's nothing to check against.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/troubleshooting-field-notes.md (reported line 49)May include surrounding context.

md
## 1. UserKnownHostsFile /dev/null Nullifies StrictHostKeyChecking

**Symptom:** `Host key verification failed` (exit 255) even though the host key is in `~/.ssh/known_hosts`.

**Root cause:** `~/.ssh/config` has `UserKnownHostsFile /dev/null` — SSH effectively has no trust store. When our skill sets `StrictHostKeyChecking=yes` (hardening v2.2.0), strict checking fails because there's nothing to check against.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/ssh-client.py (reported line 239)May include surrounding context.

python
## 1. UserKnownHostsFile /dev/null Nullifies StrictHostKeyChecking

**Symptom:** `Host key verification failed` (exit 255) even though the host key is in `~/.ssh/known_hosts`.

**Root cause:** `~/.ssh/config` has `UserKnownHostsFile /dev/null` — SSH effectively has no trust store. When our skill sets `StrictHostKeyChecking=yes` (hardening v2.2.0), strict checking fails because there's nothing to check against.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 379)May include surrounding context.

Fix applied: In ssh-run-native.sh, when HOST_KEY_CHECKING=yes, the script now forces:

text
-o UserKnownHostsFile=${HOME}/.ssh/known_hosts

This overrides the /dev/null from the SSH config and points to the real known_hosts file. A touch ensures the file exists (SSH refuses nonexistent UserKnownHostsFile paths).

Static analysis

No suspicious patterns detected.