Back to skill

Security audit

Waimai Merchant

Security checks for vulnerabilities and agentic risk

Overview

The skill is a local food-delivery merchant/product CLI, but destructive and customer-facing changes can execute immediately despite the documentation requiring confirmation.

Install only if you are comfortable with a local Chinese-language CLI that stores merchant and product data under your home directory. Treat delete, reject, suspend, product visibility, price, stock, and delivery-time commands as high-impact: require explicit user confirmation yourself, verify record IDs first, and keep backups because the tool does not enforce rollback or confirmation in code.

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

T09 · Insecure Skill Coding Practices

Warning
Location
src/commands/merchant.ts:238
Finding
Documented confirmation gates are not enforced for destructive and customer-facing operations<![CDATA[ ## Vulnerability Details **File Location**: `src/commands/merchant.ts:238-252`; related handlers in `src/commands/product.ts:277-294, 326-373`; security requirement in `SKILL.md:42-52` **Vulnerability Type**: Missing confirmation and preflight controls for high-risk state changes **Risk Level**: Medium ### Vulnerable Code The Skill documentation explicitly requires confirmation for delete, reject, suspend, delivery-time shortening, and operations that hide products: ```text 3. **Confirmation rule** - Require explicit confirmation in the current turn for delete, reject, suspend, bulk price updates, delivery-time shortening, and any operation that can hide products or change customer promises. - Show a before/after diff for price, stock, delivery time, and status changes. ``` However, merchant deletion is performed immediately: ```ts // 删除商家 merchant .command('delete <id>') .description('删除商家') .action((id) => { try { const merchant = merchantDb.getMerchantById(parseInt(id)); if (!merchant) { console.log(chalk.red('❌ 商家不存在')); process.exit(1); } merchantDb.deleteMerchant(parseInt(id)); console.log(chalk.green(`✅ 商家 "${merchant.name}" 已删除`)); } catch (error) { console.error(chalk.red('❌ 删除失败:'), error instanceof Error ? error.message : error); process.exit(1); } }); ``` Product deletion is similarly immediate: ```ts // 删除商品 product .command('delete <id>') .description('删除商品') .action((id) => { try { const prod = productDb.getProductById(parseInt(id)); if (!prod) { console.log(chalk.red('❌ 商品不存在')); process.exit(1); } productDb.deleteProduct(parseInt(id)); console.log(chalk.green(`✅ 商品 "${prod.name}" 已删除`)); } catch (error) { console.error(chalk.red('❌ 删除失败:'), error instanceof Error ? error.message : error); process.exit(1); } }); ``` Delivery-time changes also execute without checking ...[truncated 2147 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Introduce a shared confirmation function for every destructive or customer-facing action. 2. Display the exact target ID, name, current status, and proposed state before mutation. 3. Show before-and-after values for price, stock, delivery time, and status changes. 4. Require either: - Interactive confirmation through a prompt; or - An explicit non-interactive flag such as `--confirm <record-id>`. 5. Detect delivery-time reductions and require additional confirmation specifically for shortened promises. 6. Require a reason and optionally an effective time for rejection, suspension, deletion, and customer-facing changes. 7. Wrap multi-record operations in transactions. 8. Create a backup or soft-delete/audit-log record before irreversible deletion. 9. Include changed IDs, previous values, new values, and a rollback command in completion output. 10. Add automated tests proving that high-risk commands fail closed when confirmation is absent. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/db/database.ts:50
Finding
New products are automatically active despite the documented draft-first workflow<![CDATA[ ## Vulnerability Details **File Location**: `src/db/database.ts:50-67`; insertion behavior in `src/db/product.ts:14-30` **Vulnerability Type**: Unsafe default state and workflow bypass **Risk Level**: Medium ### Vulnerable Code The database schema defaults every new product to the active state: ```ts db.exec(` CREATE TABLE IF NOT EXISTS products ( id INTEGER PRIMARY KEY AUTOINCREMENT, merchant_id INTEGER NOT NULL, name TEXT NOT NULL, description TEXT, price REAL NOT NULL CHECK (price >= 0), original_price REAL CHECK (original_price >= 0), image_url TEXT, category TEXT, delivery_time INTEGER DEFAULT 30, stock INTEGER DEFAULT 0 CHECK (stock >= 0), status TEXT DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'sold_out')), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (merchant_id) REFERENCES merchants(id) ON DELETE CASCADE ) `); ``` Product creation omits the `status` column, causing SQLite to apply the unsafe default: ```ts const stmt = db.prepare(` INSERT INTO products ( merchant_id, name, description, price, original_price, image_url, category, delivery_time, stock ) VALUES ( @merchant_id, @name, @description, @price, @original_price, @image_url, @category, @delivery_time, @stock ) `); const result = stmt.run({ ...data, delivery_time: data.delivery_time ?? 30, stock: data.stock ?? 0 }); ``` This conflicts with the documented creation workflow, which describes a newly added product as inactive and instructs the user to activate it separately. ### Technical Analysis The product lifecycle is expected to separate creation from publication. Instead, the database assigns `active` when the insert omits `status`. This bypasses the intended explicit activation step and violates fail-safe default principles. Any downstream component that interprets `status = 'active'` as customer-visible will tre ...[truncated 1027 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the schema default from `active` to `inactive`: ```sql status TEXT NOT NULL DEFAULT 'inactive' CHECK (status IN ('active', 'inactive', 'sold_out')) ``` 2. Explicitly include `status` in `createProduct` and set it to `inactive` rather than relying solely on a database default. 3. Add a database migration for existing installations because `CREATE TABLE IF NOT EXISTS` will not alter an existing schema. 4. Review existing active products to distinguish intentionally published records from records activated by the unsafe default. 5. Add tests asserting that: - A newly created product is inactive. - It is absent from active-product queries. - It becomes active only after an explicit activation command. 6. Ensure the command output accurately reports the resulting state and the required next action. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
src/db/database.ts:24
Finding
SQLite foreign-key enforcement is not enabled, preventing reliable cascade deletion<![CDATA[ ## Vulnerability Details **File Location**: `src/db/database.ts:24-31`; foreign-key declaration at `src/db/database.ts:50-67` **Vulnerability Type**: Database referential-integrity misconfiguration **Risk Level**: Low ### Vulnerable Code The connection enables WAL mode but does not enable SQLite foreign-key enforcement: ```ts export function getDatabase(): Database.Database { if (!db) { ensureDataDir(); db = new Database(DB_PATH); db.pragma('journal_mode = WAL'); initializeTables(); } return db; } ``` The schema relies on a foreign-key constraint and cascade action: ```ts db.exec(` CREATE TABLE IF NOT EXISTS products ( id INTEGER PRIMARY KEY AUTOINCREMENT, merchant_id INTEGER NOT NULL, name TEXT NOT NULL, description TEXT, price REAL NOT NULL CHECK (price >= 0), original_price REAL CHECK (original_price >= 0), image_url TEXT, category TEXT, delivery_time INTEGER DEFAULT 30, stock INTEGER DEFAULT 0 CHECK (stock >= 0), status TEXT DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'sold_out')), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (merchant_id) REFERENCES merchants(id) ON DELETE CASCADE ) `); ``` ### Technical Analysis SQLite does not reliably enforce declared foreign-key constraints unless foreign-key enforcement is enabled for the database connection. The code declares `ON DELETE CASCADE` but never executes: ```sql PRAGMA foreign_keys = ON; ``` Consequently, deleting a merchant may not delete its products. It can also allow orphaned product records if data-layer functions are reused in ways that bypass the CLI's merchant-existence check. The inconsistency is partially hidden because `getAllProducts` and search queries use inner joins with the merchant table, causing orphaned records to disappear from some views while remaining in the database. ### Attack Path 1. A merchant has one or mo ...[truncated 785 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enable foreign-key enforcement immediately after opening every database connection: ```ts db = new Database(DB_PATH); db.pragma('foreign_keys = ON'); db.pragma('journal_mode = WAL'); ``` 2. Verify enforcement after connection initialization: ```ts const enabled = db.pragma('foreign_keys', { simple: true }); if (enabled !== 1) { throw new Error('SQLite foreign-key enforcement could not be enabled'); } ``` 3. Add integration tests that create a merchant and product, delete the merchant, and confirm that the associated product is removed. 4. Add a migration or maintenance routine to detect and remove or reconcile existing orphaned products. 5. Use a transaction for merchant deletion and verify the number of affected related records. 6. Report deleted merchant and product IDs so the operation's full scope is visible. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (53)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
声明描述将该 Skill 定位为“外卖商家管理”,并明确列出商品管理、价格修改、配送时间设置等核心能力。但代码仅实现 merchant CLI 的基础商家实体管理:register、list、show、update、approve、reject、suspend、delete、search。也就是说,‘商家注册’部分是匹配的,但其余声明中的关键业务能力在代码中完全未体现。相反,代码新增了审核通过、拒绝、暂停、删除、搜索等未在描述中说明的能力。因此描述不能准确代表实际行为,属于明显不一致。

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
声明总体上指向外卖商家后台管理,其中“商品管理、价格修改、配送时间设置”与代码大体一致。但该代码块实际只覆盖商品管理相关CLI命令,没有实现“商家注册”功能,因此声明包含了本代码未体现的重要能力。另一方面,代码还实现了多个更细粒度的商品运营功能,如上架、下架、售罄、删除、搜索和分类列表,这些虽可视为商品管理的子集,但并未在描述中明确体现。综合看,存在描述与实际行为的不完全匹配,主要问题是缺失已声明的商家注册能力。

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code matches only part of the declared description: merchant registration/merchant data management. However, the declared key capabilities of product management, price modification, and delivery time settings are not represented in this code chunk. Additionally, the code contains moderation/workflow capabilities—approve, reject, and suspend merchants—that are not mentioned in the description. This indicates the description does not accurately represent the supplied code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description suggests a broader external-merchant-management skill for food delivery, including product uploads, price changes, and delivery scheduling. The supplied code only manages merchant records in a database and merchant status workflow. Merchant registration is represented by createMerchant, but the other declared core capabilities are absent. Additionally, the code includes moderation/admin-style actions (approve, reject, suspend), plus deletion and search, which are not mentioned in the declared purpose. This is a material description-to-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
声明与代码有部分重合:商品管理、价格修改、配送时间设置都能在代码中看到对应接口。但代码块仅是 product 模块,聚焦商品管理,不包含商家注册相关逻辑,因此未覆盖声明中的一个核心用途。与此同时,代码还实现了多项声明未提及的能力,如商品搜索、上下架、售罄、分类查询、获取全部商品和删除商品。这些能力已超出仅“支持商家注册、商品管理、价格修改和配送时间设置”的描述范围,属于实质性的功能偏差。因此应判定为描述与实际行为不完全一致,存在 mismatch。

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The code is clearly related to the declared domain of 外卖商家 / product management, and it does support product management, price modification, and delivery time updates. However, one of the key declared purposes—merchant registration—is not implemented in this code chunk at all. In addition, the code exposes extra capabilities such as product search, category listing, and product status transitions (active/inactive/sold_out) that go beyond the stated description. Because the declared description includes a significant unsupported capability and the actual code behavior is narrower in one area while broader in others, this is a description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Yes, this is a mismatch. The declared description claims a fully featured 外卖商家管理 skill handling multiple merchant-management functions. However, the only supplied code is an empty TypeScript declaration stub (`export {}`) and contains no executable or declarative functionality related to the described behavior. There are no signs of registration flows, product handling, pricing logic, delivery-time configuration, resource access, or any other relevant implementation. This looks like placeholder or nonfunctional packaging metadata rather than the described skill behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
声明与代码只有“商家注册/商家管理”部分一致,但声明强调的核心能力还包括商品管理、价格修改和配送时间设置,而提供的代码仅处理商家账户/资料与状态管理,不涉及商品、价格或配送时段配置,因此存在明显描述-行为不匹配。此外,代码还提供了审核、拒绝、暂停、删除、搜索等未声明的管理能力,进一步表明实际范围与声明不一致。

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
声明与代码部分重合:商品管理、价格修改、配送时间设置都已实现,且与外卖商品场景一致。但代码块只覆盖 product 命令,没有实现“商家注册”能力;它只是查询商家是否存在。此外,代码还提供了多项声明未提及的商品生命周期与检索功能,如 activate/deactivate、soldout、delete、search、categories。由于缺失了声明中的一项核心能力,同时存在若干未声明功能,因此描述不能准确代表该代码块的实际行为。

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
声明描述的是一个较完整的外卖商家管理技能,涵盖商家注册、商品管理、价格更新和配送时间设置;但提供的代码块只涉及 merchants 表的CRUD和状态流转,不包含任何商品、价格、配送时间相关逻辑。因此其实际行为与声明的主要功能范围不一致。虽然“商家注册”部分是吻合的,但其余核心宣称能力缺失,且代码另外实现了审批、拒绝、暂停、删除、搜索等未声明能力,构成明显描述与行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
描述与代码部分重合:代码确实支持商品管理、价格修改和配送时间设置。但声明中的关键能力“商家注册”在该代码片段中完全没有体现;相反,代码还包含多项未在描述中提及的能力,如删除商品、上下架/售罄状态管理、搜索商品、按分类查询、列出全部商品并关联商家信息。这表明实际行为比声明更偏向完整的商品管理模块,而不是商家注册与商家管理整体。因此存在描述与行为不一致。

Known Vulnerable Dependency: lodash==4.17.23 — 2 advisory(ies): CVE-2025-13465 (lodash vulnerable to Prototype Pollution via array path bypass in `_.unset` and ); CVE-2021-23337 (lodash vulnerable to Code Injection via `_.template` imports key names)

High
Category
Supply Chain
Confidence
91% confidence
Finding
The lockfile pins lodash 4.17.23, which is affected by publicly reported issues including code injection in _.template and prototype pollution in path-handling helpers. Even though lodash is only a transitive dependency of inquirer in this file, shipping a known-vulnerable version increases risk if the skill or its dependencies process untrusted input through those APIs.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The skill documentation is written entirely in Chinese and presents all usage examples, labels, and workflow descriptions only in that language. For a general-purpose skill README, this effectively imposes a specific language/locale without user opt-in or an explicit statement that the skill is intentionally limited to a Chinese-language or region-specific use case.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The description mixes a brief English invocation hint with a Chinese-only functional description, and the rest of the document presents commands, prompts, and expected outputs entirely in Chinese. There is no statement that the skill is China-specific or that users may choose another language, which creates a locale-policy concern under the natural-language policy rule.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The stated skill purpose includes 商品管理、价格修改和配送时间设置, yet the code in this file exclusively manages merchant entities and status fields. This creates a semantic mismatch between what the skill claims to handle and what this implementation actually exposes.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The CLI descriptions and output strings are consistently hardcoded in Chinese, which forces a specific language/locale on users. The file does not offer any language selection, opt-in, or documented region-specific justification for this constraint.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest describes this skill as supporting merchant registration plus product/price/delivery-time management, but this file implements a broader merchant administration console. Commands for approving, rejecting, suspending, deleting, listing, showing, and searching merchants are not reflected in the stated description and materially expand the skill's operational scope.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The delete command removes a merchant record immediately after only checking existence, with no confirmation, dry-run, or additional safeguard. In a CLI/admin workflow, this increases the chance of accidental or scripted destructive actions, leading to unauthorized data loss if the command is invoked mistakenly or through misuse.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest describes this skill as supporting merchant registration, product management, price modification, and delivery time settings. While basic product CRUD fits product management, this file also exposes product activation/deactivation, sold-out state changes, and hard deletion commands as first-class operations, which materially extends behavior beyond the specifically advertised scope in the manifest text and triggers.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The delete command removes a product immediately after only checking existence, with no confirmation prompt, dry-run, or undo path. In an agent-driven or automated CLI context, this raises the risk of accidental or manipulated destructive actions causing integrity loss in merchant inventory data.

Description-Behavior Mismatch

Medium
Confidence
82% confidence
Finding
The manifest presents this skill as handling merchant registration and operational management tasks like product and pricing updates, but the code also exposes full merchant deletion. Destructive account-removal behavior is materially different from the listed functions and is not implied by the stated scope.

Description-Behavior Mismatch

Medium
Confidence
86% confidence
Finding
The manifest describes support for merchant registration, product management, price updates, and delivery time settings. The exported APIs also implement administrative moderation actions to approve, reject, and suspend merchants, which is a broader merchant-governance capability not stated in the description.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The manifest describes the skill as supporting merchant registration, product management, price updates, and delivery time settings. This module implements broader merchant-administration operations such as enumerating all merchants, filtering by status, deleting merchants, and changing approval/suspension status, which materially exceeds the described scope rather than serving as an obvious implementation detail.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The command descriptions, status messages, and help text throughout the file are all fixed in Chinese, with no option for users to select another language or indication that the tool is intentionally region-specific. This creates a natural-language locale policy issue because the skill effectively forces one language on all users.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill implements approval, rejection, suspension, and deletion capabilities that exceed the declared manifest scope of merchant registration and operational settings. This mismatch can mislead users or orchestration layers into granting the skill broader trust than intended, enabling unauthorized business-state changes if invoked in the wrong context.

Static analysis

No suspicious patterns detected.