Back to skill

Security audit

招标项目分析技能

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says at a high level, but it ships unsafe database defaults and gives broad, weakly controlled access to modify MySQL data.

Review before installing. Use a dedicated least-privilege MySQL account, remove the shipped root password, avoid running the custom SQL option unless you fully trust the operator and database target, and test imports on a disposable database first because the skill creates schema, modifies records, writes local analysis/export files, and adds default timeline entries.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/query.py:241
Finding
Unrestricted SQL Execution Through a Privileged Database Account## Vulnerability Details **File Location**: `scripts/query.py:28-34`, `scripts/query.py:45-53`, and `scripts/query.py:241-245`; privileged account configured at `config.json:2-10` **Vulnerability Type**: Arbitrary SQL execution with excessive database privileges **Risk Level**: High ### Vulnerable Code ```python connection = mysql.connector.connect( host=db_config['host'], port=db_config['port'], user=db_config['user'], password=db_config['password'], database=db_config['database'], charset=db_config.get('charset', 'utf8mb4') ) ``` ```python def execute_query(connection, query, params=None): """Execute an SQL query.""" try: cursor = connection.cursor(dictionary=True) cursor.execute(query, params or ()) results = cursor.fetchall() cursor.close() return results except Error as e: print(f"Query execution failed: {e}") return [] ``` ```python elif choice == '8': sql = input("Enter an SQL query: ").strip() if sql: results = execute_query(connection, sql) display_results(results, "Custom query results") ``` ```json { "database": { "host": "localhost", "port": 3306, "user": "root", "password": "MySQL@123456", "database": "bid_analysis_db", "charset": "utf8mb4", "pool_size": 5, "autocommit": true } } ``` ### Technical Analysis The interactive query interface accepts arbitrary SQL text and passes it directly to `cursor.execute()`. Unlike the predefined queries, this execution path does not constrain the statement type, target tables, or affected database objects. The connection uses the MySQL `root` account. Consequently, the effective authorization boundary is determined by the root account rather than by the legitimate read and write requirements of the tender-analysis application. Input parameterization cannot mitigate this issue because the entire SQL statement, rather than an individual value, is at ...[truncated 1414 chars]
Remediation
## Remediation Suggestions 1. Remove the arbitrary SQL option from production deployments. 2. Replace it with explicitly defined, parameterized, read-only query operations. 3. If an advanced query feature is required, parse statements with a real SQL parser and allow only a narrowly defined subset of single-statement `SELECT` queries. 4. Reject comments, multiple statements, data-definition statements, data-modification statements, stored-procedure calls, and access to schemas outside an explicit allowlist. 5. Replace the root account with a dedicated application account restricted to the required schema and operations. 6. Use separate accounts for imports and queries; the query account should have only required `SELECT` permissions. 7. Enable read-only transactions for query-only operations where supported. 8. Record security-relevant query attempts without logging credentials or sensitive query results.

T09 · Insecure Skill Coding Practices

Error
Location
config.json:2
Finding
Hardcoded Plaintext MySQL Root Credential## Vulnerability Details **File Location**: `config.json:2-10` **Vulnerability Type**: Hardcoded privileged credential **Risk Level**: High ### Vulnerable Code ```json { "database": { "host": "localhost", "port": 3306, "user": "root", "password": "MySQL@123456", "database": "bid_analysis_db", "charset": "utf8mb4", "pool_size": 5, "autocommit": true } } ``` ### Technical Analysis The project distributes a reusable MySQL root username and password in plaintext. The import, query, and test scripts load this configuration directly. Any user, process, package mirror, source repository reader, or backup system with access to the project can recover the credential. The use of the root account amplifies the exposure because compromise is not limited to the tables required by the Skill. The documentation recommends changing the password, but that does not protect installations that run with the supplied default or prevent the committed credential from remaining in repository history. ### Attack Path 1. An attacker obtains read access to the installed Skill directory, source archive, repository, log bundle, or backup containing `config.json`. 2. The attacker reads the plaintext username and password. 3. The attacker connects to a MySQL service accepting that credential, either locally or through any reachable database interface. 4. The attacker performs operations allowed to the root account. 5. If the password has been reused, the attacker may attempt it against other database environments. ### Impact Assessment The exposed credential can permit complete compromise of the affected MySQL instance if the supplied password remains active. Potential impact includes disclosure and modification of tender records, deletion of schemas, creation or alteration of database users, and access to unrelated databases permitted to the same root account. Exploitability depends on whether the default credential is valid and wheth ...[truncated 138 chars]
Remediation
## Remediation Suggestions 1. Remove the password and root username from the distributed configuration immediately. 2. Rotate the exposed credential on every system where it may have been used. 3. Rewrite repository history if the credential was committed to version control. 4. Ship a redacted `config.example.json` containing placeholders rather than operational secrets. 5. Read credentials from environment variables, a protected local credential file, or a secret-management service. 6. Restrict secret-file permissions to the account running the Skill. 7. Create a dedicated MySQL account for this application and grant only the exact schema-level permissions it requires. 8. Fail safely when credentials are absent rather than silently using a default password. 9. Add automated secret scanning to the publication and continuous-integration process.

T08 · Insecure Dependencies

Warning
Location
package.json:23
Finding
Unpinned Python Dependencies and Non-Reproducible Installation## Vulnerability Details **File Location**: `package.json:23-26` and `package.json:44` **Vulnerability Type**: Uncontrolled dependency resolution **Risk Level**: Medium ### Vulnerable Code ```json "dependencies": { "pandas": ">=1.5.0", "mysql-connector-python": ">=8.0.0", "openpyxl": ">=3.0.0" } ``` ```json "install": "pip install pandas mysql-connector-python openpyxl" ``` ### Technical Analysis The dependency declarations specify only minimum versions, while the installation command omits versions entirely. No lockfile, integrity hashes, or package-index restrictions are included. As a result, installation can resolve to dependency versions that did not exist when the Skill was audited. Future compromised, malicious, or incompatible package releases could therefore alter installation-time or runtime behavior without any change to this project. The reviewed dependency names are established packages; the finding concerns unsafe version and integrity controls rather than evidence that the current packages are malicious. ### Attack Path 1. A user installs the Skill or runs its documented dependency installation command. 2. `pip` resolves the latest versions satisfying the unrestricted constraints. 3. A future compromised or otherwise unsafe release is selected from the configured package index. 4. Package build or installation hooks execute under the privileges of the installing user. 5. The Skill subsequently imports and executes code from the uncontrolled dependency version. ### Impact Assessment A compromised dependency can execute code with the privileges of the user performing installation or running the Skill. This can affect local files, environment variables, database credentials, and any network or system resources available to that user. Even without a malicious release, uncontrolled upgrades can introduce incompatible behavior, parsing changes, or newly disclosed vulnerabilities, making deployments non-reproducible.
Remediation
## Remediation Suggestions 1. Pin every direct dependency to a specifically reviewed version. 2. Generate and maintain a lockfile or hashed requirements file that includes transitive dependencies. 3. Install with hash verification, such as `pip install --require-hashes`. 4. Explicitly configure the trusted package index rather than inheriting arbitrary user index settings. 5. Review dependency provenance, licenses, vulnerability advisories, and release changes before updates. 6. Perform dependency updates through an audited pull request and automated test process. 7. Run installation in an isolated virtual environment under an unprivileged account.

other

Warning
Location
scripts/import.py:271
Finding
Fabricated Fixed Timeline Records Inserted Into Production Project Data## Vulnerability Details **File Location**: `scripts/import.py:255-257` and `scripts/import.py:271-295` **Vulnerability Type**: Unsafe insertion of fabricated business-critical data **Risk Level**: Medium ### Vulnerable Code ```python # Insert timeline data if not existing: insert_timeline_data(cursor, project_id, project_name) ``` ```python def insert_timeline_data(cursor, project_id, project_name): """Insert timeline data.""" try: timeline_data = [ ("Obtain tender documents", "2026-03-20 08:30:00", "Tender agency", "Confirm registration by telephone", "pending"), ("Tender document deadline", "2026-03-30 17:00:00", "Tender agency", "Only six days remaining", "pending"), ("Bid submission deadline", "2026-04-10 09:30:00", "Tender agency", "Beijing time", "pending"), ("Bid opening", "2026-04-10 09:30:00", "Tender agency second-floor opening room", "Same time as submission deadline", "pending"), ] insert_sql = """ INSERT INTO project_timeline ( project_id, event_name, event_date, event_location, remarks, status ) VALUES (%s, %s, %s, %s, %s, %s) """ for event in timeline_data: cursor.execute(insert_sql, (project_id, *event)) ``` ### Technical Analysis Every newly imported project receives the same fixed event dates, locations, remarks, and statuses. These records are not extracted from the imported Excel row and are not marked as sample or placeholder data. The query functions subsequently treat these rows as real pending tasks and reminders. This violates data provenance and integrity requirements for procurement workflows, where submission and opening deadlines are business-critical facts. The unused `project_name` parameter further confirms that the timeline content is not derived from the specific project. ### Attack Pa ...[truncated 950 chars]
Remediation
## Remediation Suggestions 1. Remove all hardcoded timeline events from the production import path. 2. Extract event names, dates, locations, and remarks from explicit source columns. 3. Validate parsed dates and reject impossible or missing business-critical values. 4. Require user confirmation before inserting inferred timeline information. 5. Store provenance for each timeline record, including source file, row, field, and extraction method. 6. If demonstration data is necessary, place it in a separate test fixture or sample database and label it clearly. 7. Add automated tests confirming that unrelated projects never receive identical placeholder deadlines. 8. Review and correct existing database rows created by this function.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (28)

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The 'custom SQL query' option passes raw user input directly to cursor.execute without restricting statements to SELECT/read-only queries. This allows any user of the tool to run destructive or privilege-altering SQL such as DROP, DELETE, UPDATE, or DDL statements, defeating the apparent safety expectations of a query tool.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The manifest example recommends very broad trigger keywords such as generic business terms, which can cause the skill to activate in contexts far beyond its intended scope. In an agent ecosystem, overly broad triggers can lead to unintended invocation, confusing behavior, or accidental exposure of sensitive workflows tied to this skill.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README advertises automatic MySQL database/table creation and bulk data import but does not present any user-facing warning that local database state may be created or modified. In a skill that processes user-supplied files and supports import workflows, this omission increases the risk of users invoking destructive or persistent changes without informed consent.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The README documents trigger phrases including very broad terms such as “招标”, “投标”, “项目分析”, and especially “数据库”, which can match ordinary user conversation and cause the skill to activate outside clearly intended contexts. Because this skill can analyze files and perform database-related operations, overbroad activation increases the chance of unintended invocation and downstream state-changing actions.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill explicitly supports extracting data from Excel files and storing it into a MySQL database, but it does not warn that user-supplied content may be imported into persistent storage. This increases the risk of accidental ingestion of sensitive, regulated, or untrusted data, especially when users may not realize the skill performs storage rather than transient analysis only.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrases are very generic and overlap with normal user requests such as analyzing a file, querying projects, or generating reports. In an agent environment, this can cause the skill to activate unintentionally and perform database-related actions or data processing in contexts where the user did not explicitly intend to invoke this capability.

Vague Triggers

Medium
Confidence
87% confidence
Finding
This is a manifest-style JSON file, so vague-trigger checks apply. The skill metadata provides a name and behavior settings, but no specific trigger phrases, activation scope, or exclusion conditions, making it unclear when the skill should activate versus not activate.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The configuration forces a Chinese date format and yuan currency symbol by default, which constitutes a language/locale constraint in a natural-language-adjacent config value. There is no indication that users can choose a locale or that this region-specific behavior is documented as intentional and limited to a justified context.

Natural-Language Policy Violations

Medium
Confidence
80% confidence
Finding
The manifest description is written only in Chinese and does not indicate any user language choice or opt-in, which can amount to a language/locale policy issue when the skill is presented to a broader audience. No text in the file documents that the skill is region-specific or intentionally limited to Chinese-language users.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger list includes very generic terms such as '数据库', 'mysql', and '项目分析', which can cause the skill to activate in conversations unrelated to this specific tender-analysis workflow. Overly broad activation increases the chance of unintended execution paths, unnecessary access to connected systems, and user confusion about why a database-capable skill was invoked.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The generated JSON report includes extracted sample values from spreadsheet columns and is written to disk automatically, creating a persistent copy of potentially sensitive data without explicit user consent. In the context of tender analysis, this can leak proprietary, financial, or personal information through local files, backups, or downstream sharing.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script prints the first three rows of the spreadsheet directly to stdout, which can expose sensitive procurement or personal data in terminals, logs, CI output, or shared sessions. In this skill context, the input is an Excel tender file, which commonly contains confidential business information, making unredacted preview output materially risky.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The module docstring and all user-facing messages are written exclusively in Chinese, indicating a fixed language/locale experience. Under the policy, language constraints should offer user choice or be clearly documented as a justified region-specific limitation.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script automatically creates tables and schema objects when run, without clearly disclosing that it will make schema changes. In operational environments, silent schema creation can violate change-control expectations, create unintended structures in production, or be abused to alter persistent state beyond simple data import.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script performs inserts and updates to a MySQL database based solely on the supplied Excel file, with no confirmation prompt, dry-run mode, or explicit warning that persistent data will be modified. In an agent/skill context, this can cause unintended data corruption or unauthorized bulk changes if the tool is invoked on the wrong file or against the wrong database.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
The module docstring states this is a '数据库查询脚本' that provides multiple query methods for analyzing bidding data, which describes read/query behavior. However, the code includes `export_to_excel` and menu/CLI paths that write database contents to an arbitrary filesystem path, adding a data export side effect not reflected in the documentation.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The tool exposes arbitrary SQL execution through a menu option labeled as a query feature, but gives no warning that entered statements may modify or destroy data. In this context, the missing warning increases the likelihood of accidental misuse and harmful commands, especially because the rest of the tool is framed as a safe reporting/query interface.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
User-facing strings throughout the file, including the module description, prompts, and results, are presented only in Chinese. This imposes a specific language on users without any documented opt-in or locale justification, which matches the language/locale policy violation criteria.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
for package in required_packages:
        try:
            if package == 'mysql.connector':
                __import__('mysql.connector')
            else:
                __import__(package)
        except ImportError:
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
if package == 'mysql.connector':
                __import__('mysql.connector')
            else:
                __import__(package)
        except ImportError:
            missing_packages.append(package)
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script automatically creates missing directories during a 'test' routine without clear up-front disclosure that it will modify the filesystem. In an agent-skill context, unexpected writes are security-relevant because users may assume tests are read-only, and silent mutation can be abused to prepare state for later actions or violate least surprise.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
        # 测试分析功能
        print("\n1. 测试分析功能...")
        analyze_result = subprocess.run(
            ['python3', 'analyze.py', sample_file],
            cwd=os.path.join(skill_dir, 'scripts'),
            capture_output=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# 测试导入功能
        print("\n2. 测试导入功能...")
        import_result = subprocess.run(
            ['python3', 'import.py', sample_file],
            cwd=os.path.join(skill_dir, 'scripts'),
            capture_output=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# 测试查询功能
        print("\n3. 测试查询功能...")
        query_result = subprocess.run(
            ['python3', 'query.py', 'all'],
            cwd=os.path.join(skill_dir, 'scripts'),
            capture_output=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
73% confidence
Finding
All user-facing instructional content is presented only in Chinese, and the document does not state that it is intended for a Chinese-only audience or offer an alternative language option. Under the stated policy, forcing a specific language without opt-in can be a natural-language policy concern.

Static analysis

No suspicious patterns detected.