Back to skill

Security audit

MYSQL QUERY

Security checks for vulnerabilities and agentic risk

Overview

This database skill is mostly coherent, but it can run unrestricted SQL and has a credential-handling bug that may send a database password to an SSH server.

Review before installing. Use read-only database accounts by default, avoid production write credentials unless you explicitly need them, store secrets outside the JSON config or lock it down with owner-only permissions, set separate DB_PASSWORD_* and SSH_PASSWORD_* values, and do not use password-based SSH with this version unless the credential-confusion bug is fixed.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/db_query.py:178
Finding

Database Password May Be Reused and Transmitted as the SSH Password

Content
View full analysis
str: """Get password from environment variable or fall back to config file.""" db_name = db_config.get('name', '').replace(' ', '_').upper() env_var = f"{env_var_prefix}_{db_name}" env_password = os.environ.get(env_var) if env_password: return env_password return db_config.get('password', '') def query_database(description: str, query: str, config_path: str = None): """Query a database by description.""" config = load_config(config_path or CONFIG_PATH) db = find_database(config, description) if not db: print(f"Error: Database '{description}' not found") list_databases(config) sys.exit(1) print(f"\nQuerying database: {db.get('name')}") ssh_process = None tunnel_config = db.get('ssh_tunnel', {}) # Start SSH tunnel if needed if tunnel_config.get('enabled'): # Get SSH password from environment or config ssh_password = get_password(db, 'SSH_PASSWORD') if ssh_password: tunnel_config['ssh_password'] = ssh_password ``` ### Technical Analysis The shared `get_password()` function always falls back to the database-level `password` property when the requested environment variable is absent. This fallback is appropriate for a database password lookup but unsafe for an SSH password lookup. When `get_password(db, 'SSH_PASSWORD')` is called and the corresponding `SSH_PASSWORD_` variable is unset, the function returns `db['password']`. That value is then assigned to `tunnel_config['ssh_password']`. The tunnel launcher subsequently places it in the `SSHPASS` environment variable and invokes `sshpass -e`, causing the database password to be submitted t ...[truncated 1436 chars]
Remediation
View remediation
str: db_name = db_config.get('name', '').replace(' ', '_').upper() return os.environ.get( f"DB_PASSWORD_{db_name}", db_config.get('password', '') ) def get_ssh_password(db_config: Dict, tunnel_config: Dict) -> str: db_name = db_config.get('name', '').replace(' ', '_').upper() return os.environ.get( f"SSH_PASSWORD_{db_name}", tunnel_config.get('ssh_password', '') ) ``` Call the SSH-specific accessor as follows: ```python ssh_password = get_ssh_password(db, tunnel_config) ``` Additional hardening measures: - Prefer SSH public-key authentication over password authentication. - Keep database and SSH credentials in separate configuration properties. - Do not silently reuse one credential when another credential is missing. - Fail with a clear error when password-based SSH authentication is required but no SSH-specific password is configured. - Consider using a secret manager or operating-system credential store rather than plaintext configuration values. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:26
Finding

Plaintext Credential Configuration Is Created Without Restrictive File Permissions

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (15)

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 · scripts/INSTALL.md (reported line 8)May include surrounding context.

  1. Install MySQL client (if not already installed):
    bash
    # Ubuntu/Debian
    sudo apt update && sudo apt install mysql-client
    
    # macOS
    brew install mysql-client
    

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/db_query.py (reported line 91)May include surrounding context.

python
# Use sshpass with environment variable for password (more secure than command-line)
    if ssh_password:
        env = os.environ.copy()
        env['SSHPASS'] = ssh_password
        ssh_cmd = ['sshpass', '-e'] + ssh_cmd  # -e reads from SSHPASS environment variable
    else:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/db_query.py (reported line 143)May include surrounding context.

python
# Use sshpass with environment variable for password (more secure than command-line)
    if ssh_password:
        env = os.environ.copy()
        env['SSHPASS'] = ssh_password
        ssh_cmd = ['sshpass', '-e'] + ssh_cmd  # -e reads from SSHPASS environment variable
    else:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill invokes shell commands, reads configuration files, and relies on environment variables, but it does not declare any explicit tool scope or permissions. This increases the chance an agent will execute high-risk capabilities without clear user visibility or policy restriction, especially given the ability to reach production databases and establish SSH tunnels.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

Setup

  1. Create config file at ~/.config/clawdbot/db-config.json:
    bash
    mkdir -p ~/.config/clawdbot
    # Copy example config and edit
    

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill encourages execution of arbitrary SQL against configured databases but does not prominently warn that queries may modify or destroy data, including production systems. In this context, the danger is elevated because the skill supports partial name matching and automatic SSH tunneling, making access to sensitive live databases easier and increasing the risk of accidental destructive queries.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/INSTALL.md (reported line 8)May include surrounding context.

  1. Install MySQL client (if not already installed):
    bash
    # Ubuntu/Debian
    sudo apt update && sudo apt install mysql-client
    
    # macOS
    brew install mysql-client
    

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/INSTALL.md (reported line 14)May include surrounding context.

brew install mysql-client

text

2. **Create configuration directory and file**:
```bash
mkdir -p ~/.config/clawdbot
cp /usr/lib/node_modules/clawdbot/skills/db-query/scripts/config.example.json ~/.config/clawdbot/db-config.json

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The installation guide instructs users to place database credentials, including a password, into a local config file under their home directory without any guidance on file permissions, secret storage, or safer alternatives. In the context of a database-query skill, this increases the chance of credential exposure through weak filesystem permissions, backups, shell history around editing, or accidental inclusion in logs or source control.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code places the SSH password into the child environment for sshpass, which increases secret exposure risk because environment variables can be inherited, surfaced in debugging, core dumps, or inspected by privileged/local processes depending on platform configuration. This is especially sensitive in an automation skill handling infrastructure access.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/db_query.py (reported line 98)May include surrounding context.

python
env = None

    try:
        process = subprocess.Popen(
            ssh_cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The tool accepts and executes arbitrary SQL passed via --query without enforcing read-only semantics, despite being described as a general database query skill. In an agent context, this can enable destructive operations such as DROP, DELETE, UPDATE, schema changes, or privilege-altering statements against production databases.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/db_query.py (reported line 156)May include surrounding context.

python
]

    try:
        result = subprocess.run(
            mysql_cmd,
            capture_output=True,
            text=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code accesses sensitive database passwords from environment variables and falls back to plaintext config values, but there is no user-facing disclosure near the operation beyond internal docstrings. Under the code-file criteria, sensitive credential access should have some visible warning, prompt, or clearly documented notice to users.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

Using StrictHostKeyChecking=accept-new automatically trusts first-seen host keys, which weakens SSH host authenticity guarantees and leaves first connection vulnerable to man-in-the-middle interception. In a database tunneling tool, that can expose database credentials and query traffic to an attacker controlling the network path during initial connection.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.