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## 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
## 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.

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.

Vague Triggers

Medium
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.

Session Persistence

Medium
Category
Rogue Agent
Content
要自己挂(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
```
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.

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.

Context-Inappropriate Capability

Medium
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.

Context-Inappropriate Capability

Medium
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.

Missing User Warnings

Medium
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.

Vague Triggers

Medium
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.

Vague Triggers

Low
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.

Natural-Language Policy Violations

Low
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.

Natural-Language Policy Violations

Low
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.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/run.mjs:24