Back to skill

Security audit

MySQL Administration

Security checks for vulnerabilities and agentic risk

Overview

This MySQL administration skill is purpose-aligned, but its bundled shell scripts use unsafe command execution and credential handling that could expose passwords or run unintended local commands.

Review before installing. Use this only in controlled environments, avoid real production credentials, and do not run the bundled scripts with untrusted host, database, query, password, or file-path values. Prefer direct mysql/mysqldump calls with protected option files or mysql_config_editor, least-privileged database accounts, backups before destructive operations, and explicit confirmation for restores or permission changes.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mysql_backup.sh:71
Finding

Arbitrary Shell Command Execution in the Database Backup Script

Content
View full analysis

Vulnerability Details

File Location: scripts/mysql_backup.sh, lines 71-84
Vulnerability Type: OS command injection through unsafe command construction and eval
Risk Level: High

Vulnerable Code

bash
# Build mysqldump command
MYSQLDUMP_CMD="mysqldump -h $HOST -P $PORT -u $USER -p$PASSWORD $DATABASE"

# Add compression if requested
if [[ "$COMPRESS" == true ]]; then
  MYSQLDUMP_CMD="$MYSQLDUMP_CMD | gzip > ${OUTPUT}.gz"
  OUTPUT="${OUTPUT}.gz"
else
  MYSQLDUMP_CMD="$MYSQLDUMP_CMD > $OUTPUT"
fi

# Execute backup
echo "Backing up database: $DATABASE"
echo "Output file: $OUTPUT"
eval $MYSQLDUMP_CMD

Technical Analysis

The script constructs a shell command by interpolating values obtained from command-line arguments into a string. The string is subsequently passed to eval, causing the shell to parse its contents again as executable shell syntax.

The values supplied through --host, --port, --user, --password, --database, and --output are not validated or safely quoted. Consequently, shell metacharacters, command substitutions, redirections, pipelines, or command separators included in these values are interpreted by eval rather than passed literally to mysqldump.

Both the compressed and uncompressed branches are vulnerable. In particular, OUTPUT is inserted directly into a redirection expression, while all connection parameters become part of the reparsed command string.

Attack Path

  1. An attacker influences one of the arguments supplied to mysql_backup.sh, such as the database name, host, password, or output path.
  2. The malicious value is inserted into MYSQLDUMP_CMD without safe argument separation.
  3. The script invokes eval $MYSQLDUMP_CMD.
  4. eval reparses shell syntax contained in the attacker-controlled value.
  5. The injected command executes with the operating-system privileges of the user or Agent running the Skill.

Impact Ass

...[truncated 571 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove eval entirely.
  • Build the mysqldump invocation using a Bash array so each value remains one argument.
  • Perform redirection directly rather than storing redirection operators in a command string.
  • Implement the compression pipeline explicitly and enable set -o pipefail.
  • Validate PORT as a numeric value and enforce an appropriate range.
  • Validate output paths against the directories the Skill is authorized to write.
  • Pass credentials through a protected MySQL option file or login path rather than the command line.

A safer structure is:

bash
set -euo pipefail

args=(-h "$HOST" -P "$PORT" -u "$USER" "$DATABASE")

if [[ "$COMPRESS" == true ]]; then
  mysqldump "${args[@]}" | gzip > "${OUTPUT}.gz"
else
  mysqldump "${args[@]}" > "$OUTPUT"
fi

Authentication should be supplied separately through a mode-0600 option file or mysql_config_editor.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mysql_query.sh:61
Finding

Arbitrary Shell Command Execution in the Query Executor

Content
View full analysis

Vulnerability Details

File Location: scripts/mysql_query.sh, lines 61-78
Vulnerability Type: OS command injection through eval
Risk Level: High

Vulnerable Code

bash
# Build mysql command
MYSQL_CMD="mysql -h $HOST -P $PORT -u $USER -p$PASSWORD $DATABASE"

# Add format flags
case $FORMAT in
  table)
    MYSQL_CMD="$MYSQL_CMD -t"
    ;;
  json)
    MYSQL_CMD="$MYSQL_CMD --json"
    ;;
  csv)
    MYSQL_CMD="$MYSQL_CMD --batch --raw"
    ;;
esac

# Execute query
echo "Executing query..."
echo "$MYSQL_CMD" -e "$QUERY" | sed 's/p'"$PASSWORD"'//' | eval $MYSQL_CMD -e "$QUERY"

Technical Analysis

The connection parameters are concatenated into MYSQL_CMD, after which the resulting string and the SQL query are passed through eval. Although "$QUERY" appears quoted at the original call site, eval joins its arguments into shell source and reparses the resulting text. The original argument boundary therefore does not provide protection against shell metacharacters in the query.

The host, port, username, password, database name, and query can all influence the evaluated shell source. The password is also embedded into a dynamically constructed sed expression. This is not a safe way to redact the password and introduces additional parsing risks when the password contains delimiter characters or regular-expression syntax.

Executing arbitrary SQL is the declared function of the script; however, interpreting SQL or connection parameters as local shell syntax is unnecessary and creates a separate local code-execution vulnerability.

Attack Path

  1. An attacker causes the Agent or user to invoke the script with an attacker-controlled query or connection parameter.
  2. The value is included in the arguments supplied to eval.
  3. eval reconstructs and reparses those arguments as shell source.
  4. Shell syntax embedded in the value is executed locally instead of being pa ...[truncated 632 chars]
Remediation
View remediation

Remediation Suggestions

  • Eliminate eval and execute mysql directly.
  • Store fixed options in a Bash array and preserve each user-provided value as a distinct argument.
  • Validate FORMAT with a rejecting default branch rather than silently accepting unsupported values.
  • Do not reconstruct or print a command containing credentials.
  • Remove the password-dependent sed expression.
  • Use a protected MySQL option file or mysql_config_editor for authentication.

For example:

bash
args=(-h "$HOST" -P "$PORT" -u "$USER" "$DATABASE")

case "$FORMAT" in
  table) args+=(-t) ;;
  json)  args+=(--json) ;;
  csv)   args+=(--batch --raw) ;;
  *) echo "Unsupported format" >&2; exit 1 ;;
esac

echo "Executing query..."
mysql "${args[@]}" -e "$QUERY"

This preserves the query as one process argument and prevents shell interpretation.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/mysql_restore.sh:67
Finding

Shell and SQL Injection in the Database Restore Script

Content
View full analysis

Vulnerability Details

File Location: scripts/mysql_restore.sh, lines 67-86
Vulnerability Type: OS command injection and unsafe SQL identifier interpolation
Risk Level: High

Vulnerable Code

bash
# Build mysql command
MYSQL_CMD="mysql -h $HOST -P $PORT -u $USER -p$PASSWORD"

# Drop database if requested
if [[ "$DROP_BEFORE_RESTORE" == true ]]; then
  echo "Dropping existing database: $DATABASE"
  $MYSQL_CMD -e "DROP DATABASE IF EXISTS $DATABASE;"
  $MYSQL_CMD -e "CREATE DATABASE $DATABASE;"
fi

# Determine if input is compressed
if [[ "$INPUT" == *.gz ]]; then
  RESTORE_CMD="gunzip -c $INPUT | $MYSQL_CMD $DATABASE"
else
  RESTORE_CMD="$MYSQL_CMD $DATABASE < $INPUT"
fi

# Execute restore
echo "Restoring database: $DATABASE"
echo "From file: $INPUT"
eval $RESTORE_CMD

Technical Analysis

The restore command is assembled from untrusted command-line values and executed with eval. The input path, database name, and connection parameters can therefore introduce shell syntax into the evaluated command. This affects both compressed restoration through gunzip and uncompressed restoration through input redirection.

When --drop-before-restore is enabled, the database name is also inserted directly into destructive SQL statements:

sql
DROP DATABASE IF EXISTS $DATABASE;
CREATE DATABASE $DATABASE;

Database identifiers cannot be safely treated as arbitrary string parameters. Without strict identifier validation and identifier quoting, a crafted database value can change the meaning of the SQL statement or cause unintended database operations, subject to the permissions of the MySQL account.

Attack Path

Shell injection path:

  1. An attacker controls or influences --input, --database, or another connection argument.
  2. The value is concatenated into RESTORE_CMD.
  3. eval reparses the command string.
  4. Embedded shell syntax executes with ...[truncated 1054 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove eval and represent the MySQL invocation as a Bash array.
  • Use direct input redirection for plain files and an explicit pipeline for compressed files.
  • Enable set -euo pipefail so decompression or MySQL failures cannot be masked.
  • Use gunzip -- "$INPUT" or an equivalent end-of-options delimiter.
  • Restrict input files to authorized paths when the caller should not be able to read arbitrary local files.
  • Strictly validate database identifiers before use. An allowlist such as ^[A-Za-z0-9_$]+$ may be used if it matches the application's naming policy.
  • Quote validated identifiers as MySQL identifiers by enclosing them in backticks and safely handling any permitted backtick characters. The safest policy is to reject backticks entirely.
  • Require explicit confirmation or an additional safety control before destructive database deletion.
  • Use a least-privileged MySQL account and avoid routine restores with a global administrative account.

A safe execution pattern is:

bash
mysql_args=(-h "$HOST" -P "$PORT" -u "$USER")

if [[ ! "$DATABASE" =~ ^[A-Za-z0-9_$]+$ ]]; then
  echo "Invalid database name" >&2
  exit 1
fi

if [[ "$INPUT" == *.gz ]]; then
  gunzip -c -- "$INPUT" | mysql "${mysql_args[@]}" "$DATABASE"
else
  mysql "${mysql_args[@]}" "$DATABASE" < "$INPUT"
fi

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/mysql_backup.sh:71
Finding

Database Credentials Exposed Through Process Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/mysql_backup.sh, line 71
Additional Locations: scripts/mysql_query.sh:61, scripts/mysql_restore.sh:67, SKILL.md:71,80,90-104,149-162,220-246, and QUICKSTART.md:37
Vulnerability Type: Plaintext credential exposure through process arguments and unsafe usage guidance
Risk Level: Medium

Vulnerable Code

scripts/mysql_backup.sh:

bash
MYSQLDUMP_CMD="mysqldump -h $HOST -P $PORT -u $USER -p$PASSWORD $DATABASE"

scripts/mysql_query.sh:

bash
MYSQL_CMD="mysql -h $HOST -P $PORT -u $USER -p$PASSWORD $DATABASE"

scripts/mysql_restore.sh:

bash
MYSQL_CMD="mysql -h $HOST -P $PORT -u $USER -p$PASSWORD"

Representative guidance from SKILL.md:

bash
mysql -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER -p$MYSQL_PASSWORD -e "SELECT VERSION();"

Weak example credential from QUICKSTART.md:

bash
export MYSQL_PASSWORD="123456"

Technical Analysis

The scripts accept the database password through --password, which exposes it in the argument list of the shell script itself. They then pass it to MySQL utilities using the -pPASSWORD command-line form, exposing it again in the child process argument list.

Depending on operating-system process visibility, monitoring configuration, Agent telemetry, shell history, audit logging, crash reporting, or command logging, other users or services may capture the password. The documentation repeatedly promotes this invocation pattern, increasing the likelihood that credentials will be retained in shell history or automation logs.

Although QUICKSTART.md labels the password as an example, 123456 is a weak credential and is shown in conjunction with the MySQL root user. This can encourage insecure test configurations that are later reused.

Attack Path

  1. A user or Agent invokes one of the scripts with --password SECRET, or follows the documented ` ...[truncated 987 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove --password from the script interfaces so secrets are never supplied through process arguments.
  • Use mysql_config_editor login paths where available.
  • Alternatively, generate a temporary MySQL option file with mode 0600, pass it using --defaults-extra-file, and securely delete it after use.
  • If an environment variable must be supported for integration reasons, convert it into a protected option file before starting MySQL; do not forward it through -pPASSWORD.
  • Ensure scripts never echo reconstructed commands or credential values.
  • Update every example in SKILL.md and QUICKSTART.md to use secure authentication.
  • Replace the weak 123456 example and discourage administrative root credentials for routine querying, backup, and restore operations.
  • Use separate least-privileged accounts for querying, backup, and restoration.
  • Review shell histories, Agent logs, CI/CD logs, and monitoring data for previously exposed credentials, then rotate affected passwords.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (18)

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 · QUICKSTART.md (reported line 79)May include surrounding context.

EOF

删除备份文件

rm -rf /tmp/mysql_backup

text

## 完成!

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 · QUICKSTART.md (reported line 79)May include surrounding context.

EOF

删除备份文件

rm -rf /tmp/mysql_backup

text

## 完成!

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script performs a destructive drop-and-recreate operation based solely on a flag, with no confirmation, dry-run, or environment guardrails. A typo, automation mistake, or misuse against the wrong host/database can cause immediate and irreversible data loss.

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 · QUICKSTART.md (reported line 9)May include surrounding context.

bash
# 启动本地 MySQL 服务
sudo systemctl start mysql

# 创建测试数据库
mysql -uroot -p << EOF

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 · SKILL.md (reported line 305)May include surrounding context.

bash
# 启动本地 MySQL 服务
sudo systemctl start mysql

# 创建测试数据库
mysql -uroot -p << EOF

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The quickstart instructs users to export a MySQL password in plaintext via environment variables, including a hardcoded example value. This increases the risk of credential exposure through shell history, process inspection, debug logs, or accidental reuse in real environments, especially because no warning or safer alternative is provided.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The cleanup section drops a database named testdb using root access without warning users to verify they are connected to a non-production instance. In a quickstart context, copy-paste execution is common, so this can cause accidental destructive actions against the wrong MySQL server or reused database name.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The restore examples show direct import into a target database but do not explicitly warn that the operation can overwrite or destroy existing data. In an agent skill context, this increases the chance that an automated system or user invokes a destructive restore against the wrong environment, especially production.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The user-management examples create accounts and grant privileges without an explicit warning about their security impact. In a skill intended for operational use, this can lead to overbroad privilege changes, accidental exposure through '%' host access, or unsafe execution in production without review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document provides SET GLOBAL database configuration changes and enables logging features without warning that these affect the entire MySQL instance, may require elevated privileges, and can degrade performance or change production behavior. In a reference document, readers may copy-paste these commands directly into live systems, creating operational disruption even though the content is not overtly malicious.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Administrative commands such as OPTIMIZE TABLE, CHECK TABLE, and especially REPAIR TABLE can lock tables, consume heavy I/O, or risk service interruption if run casually on production systems. Presenting them without clear warnings or constraints increases the chance that an operator executes disruptive maintenance on a live workload.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Documenting KILL <process_id> without warning can lead users to terminate the wrong session or cancel legitimate long-running work, causing transaction rollback, user-facing outages, or data-processing interruption. Because this is an operational reference, copy-paste use is plausible and the lack of guardrails makes accidental misuse more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script accepts the database password on the command line and embeds it into a constructed shell command that is later executed with eval. This exposes credentials through process listings and shell history, and the use of eval also creates command injection risk if an attacker controls inputs such as host, user, database, or output values.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script creates an output directory and writes a full MySQL backup file, which can contain sensitive application and user data. Although it prints the destination path, there is no warning in comments or user-facing output that the operation stores potentially sensitive plaintext data on disk, especially in the non-compressed path.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This is a real vulnerability because the script constructs a shell command from untrusted inputs and executes it with eval, while also accepting an arbitrary SQL query from the caller. Even though the static finding is framed as missing user-facing warning, the more serious issue is unsafe shell execution at this line: attacker-controlled values such as HOST, USER, PASSWORD, DATABASE, or QUERY can trigger shell injection, and the command line also exposes the database password to local process inspection and logs.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file-level comments say the script 'Restores MySQL databases from backup files,' which implies loading backup data into a database. However, when --drop-before-restore is supplied, the code explicitly destroys and recreates the database before restoring it at L69-L74. That is a materially more destructive capability than the documentation suggests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Accepting the MySQL password on the command line exposes it to other local users via process listings, shell history, audit logs, and job control tooling. In many environments this can lead to credential disclosure and subsequent unauthorized database access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The natural-language instructions throughout the file are written in Chinese, and there is no indication that the skill is region-specific or that users may choose another language. Under SQP-3, forcing a specific language without opt-in can constitute a language/locale policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.