Back to skill

Security audit

lin

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent reporting purpose, but it handles live database credentials with unsafe defaults and includes under-scoped SQL and executable-invocation behavior that warrants Review before installation.

Install only in an isolated environment after replacing root/root with a dedicated read-only MySQL account, pinning dependencies, removing or tightly constraining mysql_cli fallback, validating year/database/table inputs, and confirming the output path is safe to overwrite.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
src/main.py:117
Finding

SQL Injection Through Unvalidated Database, Table, and Year Inputs

Content
View full analysis
str: if explicit_year: return explicit_year if request_text: match = re.search(r"(? str: return f""" SELECT typecode, SUM(COALESCE(tuanyi, 0)) AS tuanyi, SUM(COALESCE(zinv, 0)) AS zinv, SUM(COALESCE(nvgongteji, 0) + COALESCE(nvgongteji25, 0)) AS nvgongteji, SUM(COALESCE(zhongji, 0) + COALESCE(zhongdajibing90, 0) + COALESCE(zhongdajibing40, 0)) AS zhongji, SUM(COALESCE(qingzheng, 0)) AS qingzheng, SUM(COALESCE(yiliao, 0)) AS yiliao, SUM(COALESCE(jintie, 0)) AS jintie, SUM(COALESCE(buchongyiliao, 0)) AS buchongyiliao, SUM(COALESCE(liangai, 0)) AS liangai, SUM(COALESCE(zonghea, 0)) AS zonghea, SUM(COALESCE(zongheb, 0)) AS zongheb, SUM( COALESCE(tuanyi, 0) + COALESCE(zinv, 0) + COALESCE(nvgongteji, 0) + COALESCE(nvgongteji25, 0) + COALESCE(zhongji, 0) + COALESCE(zhongdajibing90, 0) + COALESCE(zhongdajibing40, 0) + COALESCE(qingzheng, 0) + COALESCE(yiliao, 0) + COALESCE(jintie, 0) + COALESCE(buchongyiliao, 0) + COALESCE(liangai, 0) + COALESCE(zonghea, 0) + COALESCE(zongheb, 0) ) AS total FROM {table_name} WHERE date_year = {year} AND typecode IN (1, 2, 3, 4, 5, 6) GROUP BY typecode ORDER BY typecode """ def metadata_sql(database: str, table_name: str) -> str: return f""" SELECT TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION, COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{database}' AND TABLE_NAME = '{table_name}' ORDER BY ORDINAL_POSITION """ ...[truncated 2387 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
src/main.py:27
Finding

Attacker-Selectable MySQL Executable Receives Database Credentials

Content
View full analysis
List[Dict[str, str]]: args = [ mysql_cli, "--batch", "--raw", f"--default-character-set={charset}", f"--host={host}", f"--port={port}", f"--user={user}", f"--password={password}", f"--database={database}", f"--execute={sql}", ] completed = subprocess.run(args, capture_output=True, text=True, check=True) ``` ```python def query_mysql(sql: str, **kwargs) -> List[Dict[str, str]]: try: import pymysql # noqa: F401 return _run_pymysql(sql, **kwargs) except Exception: fallback_kwargs = dict(kwargs) mysql_cli = fallback_kwargs.pop("mysql_cli", None) or "mysql" return _run_mysql_cli(sql, mysql_cli=mysql_cli, **fallback_kwargs) ``` ```python parser.add_argument("--mysql-cli", help="Optional mysql CLI path used as a fallback when PyMySQL is unavailable.") ``` ### Technical Analysis The `mysql_cli` input controls the first argument passed to `subprocess.run()`, allowing the caller to choose which local executable is launched. Although `shell=True` is not used, direct invocation of an attacker-controlled executable still provides code execution with the privileges of the Skill process. The selected program receives the database host, username, password, schema, character set, and complete SQL statement. A spoofed executable can capture these values or perform unrelated local actions. The fallback logic catches every `Exception`, not only a missing PyMySQL dependency. This causes execution of the external tool after connection, authentication, programming ...[truncated 1385 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/main.py:38
Finding

Database Password Exposed in Process Command-Line Arguments

Content
View full analysis
`. Process command lines may be visible through process inspection facilities, monitoring agents, audit records, diagnostic tools, or crash reports. Avoiding a shell prevents shell metacharacter interpretation, but it does not protect secrets contained in the process argument list. ### Attack Path 1. The Skill falls back to the MySQL CLI. 2. It starts the process with the plaintext password in its arguments. 3. A local user, monitoring service, or process-inspection tool observes the command line while the process is active or retrieves it from logs. 4. The observer extracts the database credential. 5. The credential is reused to access the configured MySQL server. ### Impact Assessment The exposed credential grants all privileges assigned to the configured database user. With the documented defaults, that may include broad administrative access as MySQL `root`. The operating-system attacker requires sufficient local process-observation access, but the resulting database compromise can extend to all schemas accessible to the account. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/main.py:391
Finding

Hardcoded Predictable Root Database Credentials and Excessive Default Privilege

Content
View full analysis
Dict[str, object]: ``` ```python parser.add_argument("--db-host", default="127.0.0.1") parser.add_argument("--db-port", type=int, default=3306) parser.add_argument("--db-user", default="root") parser.add_argument("--db-password", default="root") parser.add_argument("--database", default="test_db") ``` ```json { "connection": { "host": "127.0.0.1", "port": 3306, "user": "root", "password": "root", "database": "test_db", "charset": "utf8mb4" } } ``` ### Technical Analysis The implementation and bundled reference configuration use the predictable administrative credential `root:root`. Even when intended for development, embedding this default encourages insecure deployment and causes the Skill to request substantially more database privilege than report generation requires. The Skill performs only aggregate `SELECT` queries and schema-comment inspection. It does not require administrative account capabilities. The privileged default also magnifies the impact of SQL injection, command-line disclosure, or spoofed CLI execution. ### Attack Path 1. An operator runs the Skill without overriding the database username and password. 2. The Skill attempts authentication using the predictable `root:root` credential. 3. If the server accepts that credential, an at ...[truncated 662 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
run.sh:1
Finding

Runtime Installation of a Non-Locked Third-Party Dependency

Content
View full analysis
=1.1,<2 ``` ### Technical Analysis The launcher installs dependencies every time it runs, and the dependency is specified using a broad version range without a cryptographic hash. Consequently, two executions at different times may install different package artifacts even though the reviewed project files have not changed. No evidence shows that the named dependency is malicious. The security issue is that the effective runtime code is not locked to a reviewed artifact, creating exposure to a future compromised release, compromised package index, malicious mirror, or unsafe package-resolution configuration. ### Attack Path 1. The Skill is launched in an environment that can access a Python package index. 2. `pip install` resolves the newest available release matching `PyMySQL>=1.1,<2`. 3. A changed or compromised compatible package artifact is downloaded. 4. Package-controlled code executes during installation or later when `pymysql` is imported. 5. That code inherits the Skill process privileges and can access database credentials and report data available to the process. ### Impact Assessment A compromised dependency can execute arbitrary code with the privileges of the account running the Skill. It may access database credentials, queried insurance data, generated reports, and writable local files. The exposure occurs during every launcher execution rather than only during a controlled build or deployment phase. ]]>
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Based solely on the supplied code chunk, the implementation is just a wrapper script that installs dependencies and invokes a Python entrypoint. While this may be a normal launcher, the actual declared functionality cannot be verified from the code shown, and none of the specific described behaviors are present in the provided chunk. Therefore the supplied code does not accurately represent the declared purpose at this level of evidence.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- The default template is stored as text in `assets/beijing_office_annual_template.docx.base64.txt` and is restored to a temporary `.docx` at runtime.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding

The skill documentation describes capabilities that imply reading files, writing output files, and potentially invoking the mysql CLI, but it does not declare any tool scope or permission boundaries. In an agent environment, undeclared file and shell capabilities increase the risk of over-privileged execution, accidental access to unintended resources, and reduced auditability of what the skill is allowed to do.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation normalizes insecure default database credentials such as root/root and localhost defaults without any warning, encouraging unsafe deployments and credential reuse. If adopted as written, users may run the skill against privileged database accounts, increasing the chance of unauthorized access, data exposure, or destructive database actions if the environment is compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This is a manifest file, so SQP-2 applies to the markdown/code warning dimension via skill description context. The manifest exposes inputs for db_user, db_password, and output_path and states that it generates a Word report from MySQL metadata, but it provides no user-facing warning that the skill will access credentials and write an output file.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
94% confidence
Finding

The subprocess call itself is not using a shell, which avoids classic shell injection, but it still executes an attacker-controllable binary path via the mysql_cli parameter and passes attacker-influenced SQL built through string interpolation. In this skill context, that means a caller who can control mysql_cli, table_name, database, or year may trigger execution of an arbitrary local program or unsafe SQL against the configured database, making this a real security issue rather than a benign helper call.

Content

Scanner excerpt · src/main.py (reported line 50)May include surrounding context.

python
f"--database={database}",
        f"--execute={sql}",
    ]
    completed = subprocess.run(args, capture_output=True, text=True, check=True)
    lines = [line for line in completed.stdout.splitlines() if line.strip()]
    if not lines:
        return []

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The code creates the output directory, deletes any existing file at the target path, and moves the generated document into place. Although file generation is part of the tool's purpose, this overwrite behavior is not disclosed to the user with a confirmation prompt or explicit warning in the CLI description/help text.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code accepts database host, user, and password parameters and immediately uses them to connect to MySQL, which involves handling sensitive credentials and transmitting them to an external service. There is no confirmation prompt, visible user-facing log, or warning comment/docstring in this file explaining that credentials will be used for a live database connection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The skill's natural-language examples use only Chinese request text (帮我生成2023年业务报告) and do not state whether other languages are supported or whether Chinese is required. Under the locale-policy rule, documentation that appears to assume a specific language without user choice can be a policy concern unless the constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The run example shows only a Chinese-language --request-text invocation and does not indicate whether this is merely an example or a required locale. Without an explicit language choice or justification, the documentation may be interpreted as enforcing a specific language.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: PyMySQL has 2 known advisory(ies) (CVE-2024-36039 (PyMySQL SQL Injection vulnerability); CVE-2024-36039 (PyMySQL SQL Injection vulnerability)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency is only range-pinned as PyMySQL>=1.1,<2, so builds may resolve to a vulnerable release if environment locking is absent or stale. In this skill, the package is used to access MySQL and the cited advisory concerns SQL injection, so leaving the exact version unpinned weakens supply-chain assurance and makes it impossible to verify that deployed installs are not affected.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.