Back to skill

Security audit

publish-quality-gate

Security checks for vulnerabilities and agentic risk

Overview

The skill is a local release scanner with no exfiltration found, but its security gate can falsely report success on unscanned inputs and its install instructions use mutable remote commands.

Review before installing. The runtime script appears local-only and purpose-aligned for scanning selected release folders or zip files, but do not rely on a passing result as proof that all content was scanned. Avoid the unpinned global npx install path unless you independently trust and pin the installer source, and manually verify unsupported files such as PDFs, Office documents, images, nested archives, and missing or unreadable targets.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:108
Finding
Unpinned npx Package Creates a Supply-Chain Execution Risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:108` **Vulnerability Type**: Unpinned third-party package execution **Risk Level**: Medium ### Vulnerable Code ```bash npx skills add zhaoxinghua09-cell/agent-skills -g ``` ### Technical Analysis The documented installation procedure invokes the `skills` package through `npx` without specifying an audited version or verifying package integrity. If the package is not already available locally, `npx` may retrieve the currently published version from the configured package registry and execute it. The effective code executed by this command can therefore change independently of the reviewed Skill package. The repository reference supplied as an argument does not pin or authenticate the executable `skills` package itself. No evidence indicates that the current package is malicious. The vulnerability is the mutable and unverified supply-chain trust boundary introduced by the installation instructions. ### Attack Path 1. An attacker compromises the registry account, publication process, or upstream package associated with the unpinned `skills` command. 2. The attacker publishes a malicious package version under the expected package name. 3. A user follows the documented installation command. 4. `npx` retrieves the mutable package version and executes its lifecycle or command code. 5. The malicious package runs with the privileges of the invoking user and may modify files accessible to that account. ### Impact Assessment Successful exploitation could execute arbitrary code with the invoking user's privileges. Accessible scope could include user files, environment variables, agent configuration, and globally writable package or Skill directories. The command does not itself demonstrate privilege escalation to an administrator or root account; the maximum privileges are those already held by the user running it. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the CLI to a specifically audited version, for example `npx skills@<approved-version> ...`. - Document the expected registry, package publisher, and package checksum or provenance information. - Prefer a lockfile-backed installation or a locally verified CLI artifact. - Avoid global installation unless it is operationally necessary. - Use package-manager options that prevent unexpected lifecycle scripts where supported. - Require users to verify the package signature, integrity hash, or trusted release provenance before execution. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check_release.py:163
Finding
Unreadable or Missing Scan Targets Are Incorrectly Reported as Safe<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check_release.py:163-186, 213-240` **Vulnerability Type**: Fail-open error handling in a security gate **Risk Level**: High ### Vulnerable Code ```python def scan_path(path, label_prefix=""): """扫描文件或目录,返回命中列表""" hits = [] if os.path.isfile(path): ext = os.path.splitext(path)[1].lower() if ext in TEXT_EXTS: try: with open(path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() hits += scan_text(label_prefix + os.path.basename(path), content) except Exception: pass return hits for root, dirs, files in os.walk(path): # 跳过隐藏目录和临时目录 dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ('node_modules', '__pycache__')] for f in files: full = os.path.join(root, f) ext = os.path.splitext(f)[1].lower() if ext in TEXT_EXTS: try: with open(full, 'r', encoding='utf-8', errors='ignore') as fh: content = fh.read() rel = os.path.relpath(full, path) hits += scan_text(rel, content) except Exception: pass return hits ``` ```python all_hits = [] if os.path.isdir(target): all_hits = scan_path(target) elif zipfile.is_zipfile(target): all_hits = scan_zip(target) else: all_hits = scan_path(target) # 汇总 real_hits = [h for h in all_hits if not h['false_positive'] and not is_author_credit(h)] credit_hits = [h for h in all_hits if not h['false_positive'] and is_author_credit(h)] fp_hits = [h for h in all_hits if h['false_positive']] # 按层分组统计 layer_stats = {} for h in real_hits: layer_stats.setdefault(h['layer'], []).append(h) print("=" * 60) print("扫描结果统计:") for layer in LAYERS: ...[truncated 2361 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Verify that the target exists and is a supported regular file, directory, or valid archive before scanning. - Return exit code 2 for missing targets, permission failures, invalid archives, and other environmental errors. - Replace broad exception suppression with explicit exception handling and actionable error messages. - Track the number of discovered, successfully scanned, skipped, and failed files. - Fail closed if no eligible files were scanned or if any required file could not be read. - Avoid silently discarding decoding errors. Detect encoding where practical, or report files that cannot be decoded completely. - Add regression tests covering nonexistent paths, unreadable files, empty directories, invalid ZIP files, and partial traversal failures. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/check_release.py:19
Finding
Unsupported Release Formats Are Silently Excluded from Sensitive-Data Scanning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check_release.py:19-20, 163-198` **Vulnerability Type**: Incomplete security scanning coverage **Risk Level**: Medium ### Vulnerable Code ```python TEXT_EXTS = {'.md', '.py', '.json', '.txt', '.yml', '.yaml', '.html', '.csv', '.xml', '.ini', '.cfg', '.env'} BIN_EXTS = {'.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.pdf', '.docx', '.xlsx', '.pptx', '.zip'} ``` ```python def scan_path(path, label_prefix=""): """扫描文件或目录,返回命中列表""" hits = [] if os.path.isfile(path): ext = os.path.splitext(path)[1].lower() if ext in TEXT_EXTS: try: with open(path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() hits += scan_text(label_prefix + os.path.basename(path), content) except Exception: pass return hits for root, dirs, files in os.walk(path): # 跳过隐藏目录和临时目录 dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ('node_modules', '__pycache__')] for f in files: full = os.path.join(root, f) ext = os.path.splitext(f)[1].lower() if ext in TEXT_EXTS: try: with open(full, 'r', encoding='utf-8', errors='ignore') as fh: content = fh.read() rel = os.path.relpath(full, path) hits += scan_text(rel, content) except Exception: pass return hits ``` ```python def scan_zip(zip_path): """扫描 zip 内文本内容""" hits = [] try: with zipfile.ZipFile(zip_path) as zf: for name in zf.namelist(): ext = os.path.splitext(name)[1].lower() if ext in TEXT_EXTS: try: content = zf.read(name).decode('utf-8', errors='ignore') hits += scan_text(name, content) ...[truncated 1733 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Maintain explicit counters and output for scanned, skipped, unsupported, and failed files. - Fail closed when unsupported files are present unless the user explicitly acknowledges the incomplete coverage. - Extract text from PDF and Office formats using maintained, version-pinned libraries or isolated conversion tools. - Add optional OCR for image-based documents where release policy requires it. - Recursively inspect nested archives with strict limits on nesting depth, decompressed size, compression ratio, entry count, and processing time. - Detect file types using validated content signatures rather than relying only on filename extensions. - Treat extensionless and mismatched-extension files as unsupported or inspect them using safe content detection. - Clearly document residual coverage limitations and ensure a successful exit means every required artifact was inspected. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
声明描述的是一个包含两大阶段的质量门禁工具:发布前做四层敏感信息检查,发布后做 TRACE 五维自测。而代码实际只实现了前半部分中的一个具体脚本:扫描目录或 zip 的文本文件内容,基于正则匹配敏感信息并输出报告。这与声明的一部分相符,但明显缺失“发布后自测/TRACE 评测”这一核心能力,因此属于描述与行为不完全一致的实质性不匹配。代码没有发现额外高风险的未声明能力;问题主要是声明范围大于实际实现范围。

Credential Access

High
Category
Privilege Escalation
Content
import sys
import zipfile

TEXT_EXTS = {'.md', '.py', '.json', '.txt', '.yml', '.yaml', '.html', '.csv', '.xml', '.ini', '.cfg', '.env'}
BIN_EXTS = {'.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.pdf', '.docx', '.xlsx', '.pptx', '.zip'}

# ============ 四层检查模式 ============
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Rp1

Medium
Category
MCP Rug Pull
Confidence
87% confidence
Finding
The installation instruction uses 'npx skills' without pinning an exact package version, which can cause users to fetch whatever package version is current at execution time. If the upstream package is compromised, typo-squatted, or changed incompatibly, users may execute unintended code during installation or setup.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This Python file presents its primary docstring, console messages, and user guidance entirely in Chinese, effectively requiring Chinese comprehension for safe use. The file does not offer any language choice or explain that it is intentionally limited to a Chinese-speaking environment, which violates the language/locale policy criterion.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
This file mixes Chinese and English throughout the attestation but does not state whether language presentation is user-selectable or intentionally constrained. Because SQP-3 covers natural-language locale policy issues, this may be a mild policy concern if the skill ecosystem expects user opt-in for language choice.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The manifest contains a user-facing category value of "办公效率" on L09, which forces a specific language presentation without any indication that the skill is intended only for Chinese-speaking users. Under the policy rules, locale-specific natural language should either offer user choice or clearly document a justified regional constraint.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The visible text labels in the SVG are entirely in Chinese, including the title and all chart annotations. For a general-purpose skill asset, this can violate language/locale policy if users are not given an opt-in choice or the file is not clearly scoped to a Chinese-only audience.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
The natural-language fields in this manifest-style JSON are written entirely in Chinese, including the method and dimension notes, with no indication that the skill is Chinese-only or that users can choose another language. Under the stated policy, a language or locale constraint should be opt-in or clearly justified; this file provides neither.

Static analysis

No suspicious patterns detected.