Back to skill

Security audit

Invoice verification rule management and maintenance skill

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its stated admin purpose, but it handles API tokens and destructive validation-rule changes with weak transport and safety controls.

Review before installing. Use only against intended validation-admin environments, require HTTPS, use least-privilege short-lived tokens, avoid committing config.json, invoke a pinned or reviewed local CLI instead of generic npx, and require explicit confirmation before delete or enable/disable actions.

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

Error
Location
lib/api-client.js:50
Finding

Access Token Transmitted over Unencrypted HTTP

Content
View full analysis

Vulnerability Details

File Location: lib/api-client.js:50-57, lib/api-client.js:92-102, SKILL.md:42-50, references/examples.md:7-15
Vulnerability Type: Cleartext transmission of authentication credentials
Risk Level: High

The documentation recommends a plain-HTTP service URL, while the HTTP client permits that protocol and attaches the access token to every request.

js
function request(url, options = {}) {
  return new Promise((resolve, reject) => {
    const isHttps = url.startsWith('https:');
    const client = isHttps ? https : http;
    const urlObj = new URL(url);

    const reqOptions = {
js
async function apiRequest(endpoint, method = 'POST', body = null) {
  const config = loadConfig();
  const url = `${config.baseUrl}${endpoint}`;

  const options = {
    method,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-Access-Token': config.token
    }
  };

The documented configuration explicitly uses HTTP:

bash
export VALIDATE_BASE_URL=http://global-masterdata-http.default.yf-bw-test-2.test.51baiwang.com
export VALIDATE_TOKEN=your-token-here
json
{
  "baseUrl": "http://global-masterdata-http.default.yf-bw-test-2.test.51baiwang.com",
  "token": "your-token-here"
}

Technical Analysis

HTTP does not provide transport encryption, server authentication, or message integrity. When the configured base URL uses HTTP, the X-Access-Token header, request bodies, and API responses are transmitted in cleartext.

An attacker capable of observing or modifying traffic between the CLI and the service could capture the token or tamper with administrative requests. Because this CLI supports create, update, enable, disable, and delete operations, the consequences depend on the permissions granted to the intercepted token.

Attack Path

  1. A user follows the documented setup and co ...[truncated 992 chars]
Remediation
View remediation

Remediation Suggestions

  • Require the configured base URL to use the https: protocol and reject HTTP URLs before constructing a request.
  • Replace all HTTP URLs in SKILL.md, references/examples.md, and CLI help text with verified HTTPS endpoints.
  • If plain HTTP is unavoidable for isolated local development, require an explicit opt-in flag such as ALLOW_INSECURE_HTTP=true, display a prominent warning, and prohibit its use with non-loopback hosts.
  • Preserve normal TLS certificate and hostname validation; do not introduce options that disable certificate verification.
  • Rotate tokens that may already have been transmitted over untrusted HTTP networks.
  • Apply least-privilege and short expiration periods to API tokens to reduce the impact of interception.

T09 · Insecure Skill Coding Practices

Warning
Location
.gitignore:1
Finding

Plaintext Credential Configuration Is Not Excluded from Version Control

Content
View full analysis

Vulnerability Details

File Location: .gitignore:1, SKILL.md:46-51, references/examples.md:11-17
Vulnerability Type: Insecure plaintext secret storage and accidental credential disclosure
Risk Level: Medium

The documentation directs users to store an access token in a project-level config.json file:

json
{
  "baseUrl": "http://global-masterdata-http.default.yf-bw-test-2.test.51baiwang.com",
  "token": "your-token-here",
  "appId": "your-app-id-here"
}

However, the complete .gitignore contains only:

gitignore
package-lock.json

Therefore, the credential-bearing config.json is not protected from accidental source-control inclusion.

Technical Analysis

Access tokens are bearer-style credentials and should not be stored in routinely tracked project files. A developer following the supplied instructions can create config.json at the project root and unintentionally add it to a commit.

The file is also read as ordinary plaintext without checking or enforcing restrictive filesystem permissions. Although this alone does not expose the file remotely, it increases the likelihood of disclosure through repository publication, shared workspaces, backups, build artifacts, or access by other local users.

Attack Path

  1. A user follows the documented configuration method and places a valid token in config.json.
  2. Because .gitignore does not exclude the file, it appears as an untracked source-control file.
  3. The user accidentally commits and pushes it, archives the project, or shares the workspace.
  4. An attacker with access to the repository, archive, backup, or local file reads the plaintext token.
  5. The attacker submits authenticated requests using that token.
  6. The attacker gains the API capabilities granted to the exposed credential until it expires or is revoked.

Impact Assessment

Exploitation can expose the configured access token and potentially ...[truncated 286 chars]

Remediation
View remediation

Remediation Suggestions

  • Add config.json and other local credential-file variants to .gitignore.
  • Supply a safe config.example.json containing placeholders only.
  • Prefer environment injection from a secret manager or CI credential store rather than persistent plaintext files.
  • If file-based configuration remains supported, document restrictive permissions such as owner-only read/write access.
  • Add automated secret scanning to pre-commit hooks and CI pipelines.
  • Ensure build, packaging, and archive processes exclude local configuration files.
  • Immediately revoke and rotate any token found in repository history; deleting the latest copy does not remove it from prior commits.

T09 · Insecure Skill Coding Practices

Warning
Location
commands/rules.js:48
Finding

Invalid Status Values Silently Trigger Resource Disablement

Content
View full analysis

Vulnerability Details

File Location: commands/rules.js:48-55, commands/scenes.js:33-40, lib/utils.js:8-11
Vulnerability Type: Improper input validation leading to unintended state-changing operations
Risk Level: Medium

Rule status handling accepts every nonempty value and maps anything other than the exact string enabled to the disable endpoint:

js
async 'enable-rule'(p) {
  requireParams(p, ['id', 'status']);
  const isEnable = p.status === 'enabled';
  const endpoint = isEnable ? '/admin/validateRule/enable' : '/admin/validateRule/disable';
  ok(`规则已${isEnable ? '启用' : '禁用'}`, await apiRequest(endpoint, 'POST', { id: int(p.id) }));
},

Scene status handling repeats the same behavior:

js
async 'enable-scene'(p) {
  requireParams(p, ['id', 'status']);
  const isEnable = p.status === 'enabled';
  const endpoint = isEnable ? '/admin/validateScene/enable' : '/admin/validateScene/disable';
  ok(`场景已${isEnable ? '启用' : '禁用'}`, await apiRequest(endpoint, 'POST', { id: int(p.id) }));
},

The shared validator checks only whether a value is present:

js
function requireParams(params, fields) {
  const missing = fields.filter(f => params[f] === undefined || params[f] === '');
  if (missing.length > 0) throw new Error(`缺少必填参数:${missing.join(', ')}`);
}

Technical Analysis

The handlers implement a binary decision using status === 'enabled'. Values such as enable, Enabled, draft, true, or arbitrary attacker-controlled strings are accepted by requireParams() but resolve to the disable branch.

This is unsafe for a state-changing command because malformed input does not fail closed. A typographical error or untrusted automation input can therefore perform the opposite administrative operation from what the operator intended.

The ID conversion also defaults malformed IDs to zero, but exploitability of ID zero depends on server-side behavior. The confi ...[truncated 1085 chars]

Remediation
View remediation

Remediation Suggestions

  • Validate status against an explicit allowlist before selecting an endpoint:
js
if (!['enabled', 'disabled'].includes(p.status)) {
  throw new Error('status must be either enabled or disabled');
}
  • Reject invalid values instead of treating them as disable requests.
  • Consider exposing separate enable-rule, disable-rule, enable-scene, and disable-scene actions so the operation is explicit.
  • Validate IDs as positive integers and reject malformed, zero, negative, or partially numeric values.
  • Add tests covering invalid casing, misspellings, booleans, empty values, and unsupported status names.
  • For high-impact administrative operations, display the target ID and intended state before execution or support an explicit confirmation mechanism.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

描述覆盖范围明显大于代码实际能力。代码只针对“校验规则”资源进行有限的 CRUD/状态操作,没有看到任何“规则组”或“校验场景”相关接口,也未体现统一 CLI 的更广泛场景处理逻辑。虽然描述中提到的部分能力(规则创建、查询、启停)与代码一致,但其核心宣称的资源范围和全流程管理能力与实际实现不符,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

声明描述的是一个涵盖校验规则、规则组、校验场景的统一管理技能,范围较大;但实际代码块只处理“校验场景”资源,且仅包含创建、查询、启停和删除四类操作,没有任何规则或规则组相关实现。因此描述对代码能力有明显夸大,主用途比实际实现更宽。虽然场景配置、启停和查询与声明部分一致,但整体仍构成描述与行为不匹配。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
81% confidence
Finding

The skill documents use of environment variables for authentication and runtime configuration but does not declare any explicit tool scope or permissions boundary. In practice, this can cause an agent platform to invoke the skill without clear restrictions around environment access, increasing the chance of unintended secret exposure or unauthorized use of ambient credentials.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The description uses broad trigger language such as handling requests like 'help me create a rule' or 'check the scene list,' which can overlap with ordinary conversation and cause the skill to activate too eagerly. In an agent system tied to mutating back-end APIs, over-broad activation increases the risk of unintended privileged actions or sensitive queries without sufficient user confirmation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The natural-language description and trigger examples are entirely specified in Chinese and imply the skill is intended to operate on Chinese user phrasing, but there is no explicit user choice or documented locale restriction. This can violate language/locale policy when a skill implicitly forces one language without opt-in.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The initialization flow runs npx vr help and may trigger package resolution/execution without pinning an exact version or verifying package provenance. Unpinned npx execution creates a supply-chain risk: a malicious or replaced package version could run arbitrary code during install or invocation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The documented fallback to npm install after npx vr help further increases supply-chain exposure because it installs dependencies from the network without any version pinning details in the skill documentation. If a dependency is compromised, the install step can execute lifecycle scripts and arbitrary code.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The instruction to call npx --prefix /path/to/validation-rule-management vr <action> still relies on unpinned npx resolution/execution semantics. In an agent context, repeatedly invoking a network-resolved package broadens the attack surface for package substitution or dependency compromise.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The command reference normalizes use of npx vr <action> across the skill without version pinning, encouraging repeated execution of a potentially mutable package entrypoint. This is dangerous because a compromised package or dependency can execute arbitrary code in the agent/runtime environment.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

This command example uses npx vr without pinning or provenance verification for a state-changing operation. If the CLI package is maliciously altered, the attack could be hidden behind a legitimate administrative workflow and execute arbitrary code before or during the API call.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The unpinned npx vr invocation for querying rule groups exposes the same supply-chain risk as mutating commands because arbitrary code can run at startup regardless of the business action. In an agent setting, even read-oriented commands may access local config and tokens, amplifying the impact.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Using unpinned npx vr for update operations combines package execution risk with the possibility of unauthorized remote changes. A compromised package could both exfiltrate credentials and alter validation configuration in ways that are hard to detect.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The delete operation is documented through an unpinned npx command, so a malicious package could perform arbitrary code execution while also disguising destructive business actions as normal administration. This raises both host compromise and remote data integrity risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation exposes a direct delete-rule-group command with no warning, confirmation, or safeguard guidance. In an agent-assisted workflow, that omission makes accidental or prompt-induced destructive actions more likely, potentially removing configuration that affects validation behavior for many downstream operations.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The create-rule example relies on unpinned npx, exposing the environment to package substitution or dependency compromise. Because the CLI also uses tokens and network endpoints, a malicious package could capture secrets and manipulate rule definitions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The query-rules example still executes through unpinned npx, which is sufficient for arbitrary code execution even without mutation of remote state. The skill context makes this more dangerous because authentication tokens are expected to be present in env vars or config files.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The enable/disable rule command uses the same unpinned execution model, allowing a compromised package to alter rule state and potentially weaken validation controls. In systems enforcing business or compliance rules, that could directly reduce protective checks.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The delete-rule example uses unpinned npx, combining arbitrary code execution risk with destructive business impact. An attacker could abuse this path to both compromise the runtime and silently remove critical validation rules.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The rule deletion command is presented as a one-step action without any safety guidance. Deleting validation rules can weaken control coverage and create integrity/compliance gaps, especially if an agent executes the command based on ambiguous user input.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The create-scene command is another unpinned npx execution point vulnerable to supply-chain compromise. Since scenes govern validation behavior, malicious execution could alter business logic and exfiltrate tokens or configuration.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The query-scenes example retains the same arbitrary package execution risk from unpinned npx. Even read operations may reveal internal metadata and access secrets through config loading, so the context increases the danger beyond a harmless query.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The enable-scene command can be abused through a compromised package to weaken or disable validation scenarios while running arbitrary code. That could directly impact downstream enforcement and integrity of validation workflows.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The delete-scene command is especially risky because an untrusted npx package can both execute arbitrary code and perform destructive remote actions. In administrative automation, this could lead to hard-to-detect sabotage of validation coverage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The scene deletion command is another destructive operation documented without confirmation or rollback guidance. Since scenes orchestrate groups and rules, deleting one can have broader operational impact than a single object removal.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The troubleshooting guidance again instructs npx vr, reinforcing insecure execution patterns throughout the skill. Repetition matters because it normalizes a dangerous installation/runtime path for operators and agents.

Content

No source excerpt is available for this finding.