Back to skill

Security audit

lin

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but its database-writing script has unsafe defaults and SQL injection risks that could affect a user's MySQL data.

Review before installing or running. Use only with trusted URLs and a restricted MySQL account, avoid URLs containing tokens or personal data, and expect the script to create database objects and store raw query parameter values. The publisher should validate identifiers, remove root/root defaults, avoid printing raw parameters, and document persistence clearly.

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/save_url_params.py:35
Finding
SQL Injection Through Attacker-Controlled URL Parameter Names## Vulnerability Details **File Location**: `scripts/save_url_params.py:35-41` and `scripts/save_url_params.py:62-67` **Vulnerability Type**: SQL injection through unvalidated identifiers **Risk Level**: High **Vulnerable Code**: ```python # Build column definitions column_defs = ", ".join(f"{col} VARCHAR(255)" for col in columns) create_sql = f""" CREATE TABLE IF NOT EXISTS {TABLE_NAME} ( id INT AUTO_INCREMENT PRIMARY KEY, {column_defs} ) """ cursor.execute(create_sql) ``` ```python columns = ", ".join(flat_params.keys()) placeholders = ", ".join(["%s"] * len(flat_params)) values = list(flat_params.values()) insert_sql = f"INSERT INTO {TABLE_NAME} ({columns}) VALUES ({placeholders})" cursor.execute(insert_sql, values) ``` ### Technical Analysis URL query parameter names originate from user-controlled input and are used directly as SQL column identifiers. Although the inserted values use parameter placeholders, placeholders do not protect table or column identifiers. Consequently, a specially crafted parameter name can introduce SQL syntax into both the `CREATE TABLE` statement and the subsequent `INSERT` statement. The exact ability to execute multiple statements depends on the MySQL connector configuration and server behavior. Even where stacked statements are disabled, malicious identifiers can still alter query structure, trigger persistent schema problems, or repeatedly cause database errors and denial of service. ### Attack Path 1. An attacker supplies a URL containing a specially crafted query parameter name. 2. `parse_qs(parsed.query)` preserves that attacker-controlled name as a dictionary key. 3. `flat_params.keys()` is passed to `create_table_if_not_exists()`. 4. The name is interpolated without validation into `column_defs`. 5. The same name is later interpolated into the `INSERT` column list. 6. MySQL parses and executes SQL whose structure is partially controlled by th ...[truncated 750 chars]
Remediation
## Remediation Suggestions - Do not derive database columns directly from URL parameter names. Prefer a fixed normalized schema such as `url_id`, `parameter_name`, and `parameter_value`. - If dynamic identifiers are unavoidable, enforce a strict allowlist such as `^[A-Za-z_][A-Za-z0-9_]{0,63}$`. - Reject reserved words, duplicate normalized names, oversized identifiers, and all names that fail validation. - Quote identifiers using a connector-supported, database-specific mechanism after validation. Do not treat quoting alone as sufficient validation. - Continue using bound parameters for values. - Execute database operations through a dedicated account with access only to the required schema and operations. - Add tests using punctuation, spaces, backticks, parentheses, comments, reserved words, and oversized query keys to verify rejection.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/save_url_params.py:21
Finding
SQL Injection Through Unvalidated Database Name Configuration## Vulnerability Details **File Location**: `scripts/save_url_params.py:8` and `scripts/save_url_params.py:21` **Vulnerability Type**: SQL injection through an unvalidated database identifier **Risk Level**: Medium **Vulnerable Code**: ```python DB_NAME = os.getenv("DB_NAME", "test_db") ``` ```python if create_if_missing: cursor.execute(f"CREATE DATABASE IF NOT EXISTS {DB_NAME}") ``` ### Technical Analysis `DB_NAME` is obtained from the process environment and interpolated directly into a SQL statement as an identifier. No syntax validation or safe identifier quoting is performed. SQL parameter placeholders generally cannot be used for database identifiers. The correct defense is strict identifier validation followed by database-appropriate quoting, or elimination of runtime database creation. If an attacker can influence the environment used to launch this script, the attacker can affect the SQL statement parsed by MySQL. ### Attack Path 1. An attacker or compromised deployment process gains control over the `DB_NAME` environment variable. 2. A crafted value containing SQL syntax is assigned to `DB_NAME`. 3. The script calls `connect_db()` with database creation enabled. 4. The crafted value is inserted directly into `CREATE DATABASE IF NOT EXISTS`. 5. MySQL parses the resulting attacker-influenced SQL. 6. Exploitation scope is determined by connector support for multiple statements and the privileges of the configured database account. ### Impact Assessment The vulnerability can cause database creation failures and denial of service. Under permissive connector settings and a privileged account, it may permit unauthorized database operations. Exploitation requires influence over the process environment or deployment configuration, so it is less directly exposed than the URL parameter issue. However, the script's default use of the MySQL `root` account can magnify the impact to other databases manage ...[truncated 21 chars]
Remediation
## Remediation Suggestions - Provision the database outside the request-processing script and remove runtime `CREATE DATABASE` functionality. - Require `DB_NAME` to match a strict identifier pattern, with an explicit maximum length. - Safely quote the validated database identifier using MySQL-compatible identifier quoting. - Reject invalid configuration and terminate before connecting rather than attempting to repair it dynamically. - Restrict control of deployment environment variables to trusted administrators. - Use a dedicated account that cannot create or delete databases during normal operation.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/save_url_params.py:6
Finding
Insecure Privileged Default Database Credentials## Vulnerability Details **File Location**: `scripts/save_url_params.py:6-8` **Vulnerability Type**: Weak default credentials and excessive database privileges **Risk Level**: Medium **Vulnerable Code**: ```python DB_HOST = os.getenv("DB_HOST", "localhost") DB_USER = os.getenv("DB_USER", "root") DB_PASSWORD = os.getenv("DB_PASSWORD", "root") DB_NAME = os.getenv("DB_NAME", "test_db") ``` ### Technical Analysis When environment configuration is absent, the script silently attempts to authenticate using the predictable `root`/`root` credential pair. This creates an unsafe deployment default and encourages operation with MySQL's administrative account. The script also creates databases at runtime, requiring privileges beyond those normally needed to save URL parameters. Excessive privileges amplify the impact of the SQL injection vulnerabilities elsewhere in the script. ### Attack Path 1. An operator deploys the skill without setting `DB_USER` or `DB_PASSWORD`. 2. The script automatically attempts authentication with `root`/`root`. 3. If the MySQL server accepts those credentials, the script runs with administrative database privileges. 4. An attacker then supplies malicious URL parameter names, or influences database configuration. 5. Attacker-influenced SQL executes with the excessive privileges of the root database account. Alternatively, any party able to reach a MySQL deployment configured with the same weak root credentials may attempt direct authentication if network access permits it. ### Impact Assessment Where the default credentials are accepted, compromise can extend to every database object accessible to the MySQL root account rather than remaining limited to `url_parameters`. Potential effects include unauthorized reading, modification, creation, or deletion of databases and user data. No evidence in the reviewed code establishes operating-system root access; the affected privilege boundary is th ...[truncated 117 chars]
Remediation
## Remediation Suggestions - Remove all default usernames and passwords. - Fail closed with a clear configuration error when required credentials are missing. - Retrieve credentials from an approved secret manager or protected runtime secret facility. - Create a dedicated service account restricted to the required schema and operations. - Provision databases and schema through a separate administrative migration process. - Deny the runtime account permission to create or drop databases, manage users, or access unrelated schemas. - Rotate any deployed `root`/`root` credentials and review database logs for unauthorized access. - Configure MySQL to limit administrative accounts to trusted interfaces and hosts.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/save_url_params.py:70
Finding
Sensitive URL Parameters Exposed in Process Output## Vulnerability Details **File Location**: `scripts/save_url_params.py:70` **Vulnerability Type**: Sensitive information exposure through logging **Risk Level**: Low **Vulnerable Code**: ```python print(f"Inserted parameters into {TABLE_NAME}: {flat_params}") ``` ### Technical Analysis The script prints the complete parameter dictionary, including every raw value supplied in the URL. Query strings commonly contain API keys, access tokens, signatures, session identifiers, email addresses, and other personal or confidential data. Standard output may be captured by shell logs, CI systems, container logging drivers, orchestration platforms, or centralized monitoring services. Printing values therefore creates an additional, potentially less protected copy of information that was intended for database storage. ### Attack Path 1. A legitimate user or upstream service provides a URL containing a sensitive query parameter. 2. The script parses the parameter and inserts it into MySQL. 3. The script prints the entire `flat_params` dictionary after insertion. 4. The execution environment captures standard output. 5. Users or systems with log access can retrieve the sensitive parameter value, potentially after the original URL has expired or been removed. ### Impact Assessment Exposed values may enable account or API impersonation if they contain active credentials or tokens. Personal data may also be retained outside the database's intended access controls and retention policy. The scope is limited to parameter values processed by the script and to parties that can access its output or downstream logs. The severity increases when URLs contain reusable credentials or when logs are broadly accessible or retained for long periods.
Remediation
## Remediation Suggestions - Do not print raw query parameter values. - Log only non-sensitive metadata, such as the number of parameters stored and a request correlation identifier. - If parameter names must be logged, apply an explicit allowlist and redact known-sensitive names such as `token`, `key`, `secret`, `password`, `signature`, and `session`. - Treat all unknown values as sensitive by default. - Configure production logging with appropriate access controls, encryption, retention limits, and deletion procedures. - Review existing logs and remove or rotate any credentials that may already have been exposed.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises behavior that requires network and environment-backed code execution but does not declare any tool scope or permission boundaries. This increases the chance the agent will run the skill with broader-than-necessary privileges, making unintended outbound connections or access to environment-provided secrets more likely.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill stores URL-derived data in MySQL and may auto-create schema based on input-derived parameter names, but the description does not warn users about persistence, sensitivity of query parameters, or schema side effects. URLs often contain tokens, session identifiers, emails, and other sensitive values, so silent storage can create privacy, security, and data-retention risks.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script persists all URL query parameters directly into a database without any filtering, minimization, or warning, which can capture sensitive data such as tokens, session identifiers, email addresses, or internal tracking values. Because query strings often contain secrets in real environments, indiscriminate storage increases the risk of long-term exposure through database compromise, backups, logs, or later misuse.

Context-Inappropriate Capability

Low
Confidence
76% confidence
Finding
The manifest describes a URL-parameter extraction and storage skill, but the code additionally depends on process environment access for DB_HOST, DB_USER, DB_PASSWORD, and DB_NAME. Accessing environment configuration, especially credentials, is a broader capability than the manifest states and is not explicitly declared as part of the skill's scope.

Missing User Warnings

Low
Confidence
79% confidence
Finding
The script automatically creates a database and table if they do not exist, which modifies the user's database environment. While this behavior is part of persistence, the only visible messaging is an insertion print after the fact, so the code lacks an explicit upfront warning that it may create database objects.

Static analysis

No suspicious patterns detected.