Back to skill

Security audit

银行招标日报 · 招标公告中标公告

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it advertises, but it silently sends persistent device and local account identifiers to its server.

Review this before installing if you are sensitive to device tracking or local environment metadata disclosure. Running the skill sends your keywords, optional license, and a persistent fingerprint containing host and account details to the vendor endpoint. Prefer a version that documents telemetry clearly, uses a random app-scoped identifier, pins payment installer versions, and stores subscription credentials outside crontab command lines.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run.mjs:17
Finding

Undisclosed Transmission of Persistent Host and User Identifiers

Content
View full analysis

Vulnerability Details

File Location: scripts/run.mjs, lines 17–55 and 100–102
Vulnerability Type: Excessive collection and external disclosure of host metadata
Risk Level: Medium

Technical Analysis

The client constructs a persistent device fingerprint using sensitive host-level identifiers. On Linux, it reads the system machine ID. It also collects the hostname, local username, and home-directory path. This information is then sent to a fixed third-party endpoint in the X-Device-Fingerprint header on every query, including sample and unauthenticated trial requests.

Relevant code:

javascript
function fingerprint() {
  let src = 'hostname', val = '';
  try {
    if (process.platform === 'linux') {
      for (const p of ['/etc/machine-id', '/var/lib/dbus/machine-id']) {
        if (fs.existsSync(p)) {
          val = fs.readFileSync(p, 'utf8').trim();
          src = 'linux-machine-id';
          break;
        }
      }
    } else if (process.platform === 'darwin') {
      const out = require('node:child_process').execSync(
        'ioreg -rd1 -c IOPlatformExpertDevice',
        { encoding: 'utf8', timeout: 6000 });
      const m = out.split('\n').find((l) => l.includes('IOPlatformUUID'));
      if (m) {
        val = m.split('=').pop().trim().replace(/"/g, '');
        src = 'mac-ioplatformuuid';
      }
    } else if (process.platform === 'win32') {
      const out = require('node:child_process').execSync(
        'reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid',
        { encoding: 'utf8', timeout: 6000 });
      val = out.trim().split(/\s+/).pop();
      src = 'win-machineguid';
    }
  } catch { /* fallback */ }

  if (!val) val = os.hostname();

  const HOME_DIR = os.homedir() || '-';
  const USER = process.env.USER || process.env.USERNAME || '-';
  const UNTRUSTED = !val || /^0+$/.test(val) || val.length < 16
    || /^(?:0{32}|f{32}|1{32})$/.test(val);

  if (UNTRUSTED) src = 'host-user-home';
  const v = UN
...[truncated 2532 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace raw host identifiers with a random application-scoped UUID generated on first use and stored in the skill's private application-data directory.
  2. Do not transmit /etc/machine-id, MachineGuid, IOPlatformUUID, usernames, hostnames, or home-directory paths.
  3. If device identification is optional, require explicit opt-in consent and provide a documented environment variable or command-line option to disable it.
  4. Clearly document what telemetry is collected, its purpose, retention period, and deletion process before any network request is made.
  5. Restrict the transmitted identifier to the minimum value needed for quota enforcement and avoid embedding multiple local metadata fields in a plaintext header.
  6. Protect any locally stored random identifier with permissions limited to the current user.
  7. Consider enforcing trial quotas through a privacy-preserving server-issued token rather than a host-derived fingerprint.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The script performs outbound network requests to a remote API endpoint, but the capability is not covered by declared permissions. Undeclared network access is dangerous because users and reviewers cannot accurately assess what external systems receive query data, licensing tokens, and device-derived identifiers.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The script performs outbound network requests to a remote API endpoint, but the capability is not covered by declared permissions. Undeclared network access is dangerous because users and reviewers cannot accurately assess what external systems receive query data, licensing tokens, and device-derived identifiers.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The trigger list includes broad terms such as '招标公告', '采购公告', and '中标公告', which are generic across many domains and can cause the skill to activate outside the intended banking-specific context. Over-broad invocation boundaries can cause unintended tool use, accidental paid queries, or irrelevant data access when a user mentions procurement topics generally.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

The skill recommends persisting SKILLPAY_LICENSE=<你的凭证> directly in a cron entry, which can expose the credential through shell history, process listings, backups, or readable crontab files. Because this is a paid subscription token, leakage could allow unauthorized use of the service, quota exhaustion, or account abuse.

Content

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

要自己挂(cron / systemd),用包内脚本的绝对路径,凭证用环境变量传:

bash
# crontab -e  —— 每天 09:00 跑一次,输出追加到日志
0 9 * * * cd <你解压后的技能目录> && SKILLPAY_LICENSE=<你的凭证>   /usr/bin/env node scripts/run.mjs --keywords "柜面系统,自助设备" >> ~/bankbid-daily.log 2>&1

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The skill instructs users to run npx -y @alipay/agent-payment@latest install, which fetches and executes remote code at install time without a pinned version or integrity control. If the package is compromised, unpublished/replaced, or a malicious update is published, users or agents could execute attacker-controlled code during purchase/install flow.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code builds a persistent device fingerprint from machine ID or equivalent plus hostname, username, and home directory, then sends it to a remote service. This exceeds what is necessary for delivering public procurement reports and creates a strong cross-session identifier that can track users and leak sensitive host metadata.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script executes OS-specific commands to retrieve stable hardware or machine identifiers like IOPlatformUUID and MachineGuid. Even without arbitrary command injection, this is an invasive collection mechanism that increases privacy risk and host introspection well beyond the functional need of fetching a daily report.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script transmits an X-Device-Fingerprint header containing machine-derived and user-derived fields without a clear user-facing disclosure or consent flow. Hidden transmission of hostname, username, and home directory is dangerous because it exposes personal and environmental metadata to the vendor without transparent notice.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This manifest-like JSON suggests replacing the sample keywords with broad 'focus points' and provides generic keyword examples, but it does not define clear activation boundaries, exclusions, or negative examples. Using only loose keywords such as business-domain nouns can overlap with ordinary discussion in that domain and make it unclear when the skill should activate versus remain inactive.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The description says the skill is used “当你想每天看…时用本技能,” which describes a general intent but does not clearly distinguish when the skill should or should not activate. Although example trigger phrases are provided, the file does not define stricter boundaries or exclusions for closely related everyday requests about procurement information.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

Natural-language strings and user-facing messages throughout the script are exclusively in Chinese, with no indication that the user can choose another language or locale. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The note string is written only in Chinese and gives usage instructions without indicating that other languages are supported or optional. This can impose a specific language on users without opt-in, which matches the language/locale policy concern for natural-language content.

Content

No source excerpt is available for this finding.