Back to skill

Security audit

本地研究资料查询

Security checks for vulnerabilities and agentic risk

Overview

The main archive-search behavior is mostly coherent, but the package also ships under-disclosed publishing and packaging utilities with external publish and destructive filesystem capabilities.

Review this carefully before installing. The query tool itself is aimed at local archive search and defaults away from private scopes, but the package contains extra publish/build scripts and may send retrieved archive text into an AI analysis component before saving reports. Install only if you trust the publisher, are comfortable with the local archive data flow, and will avoid running the packaging or publishing scripts except in a controlled development context.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (2)

T01 · Skill Instruction Hijacking

Warning
Location
scripts/unified_query.py:190
Finding

Indirect Prompt Injection Through Untrusted Archive Content

Content
View full analysis

Vulnerability Details

File Location: scripts/unified_query.py, lines 190-236
Vulnerability Type: Indirect prompt injection
Risk Level: Medium

Vulnerable Code

python
def build_summary_prompt(query: str, days: float, items: list[dict[str, Any]]) -> str:
    snippets: list[str] = []
    for index, item in enumerate(items[:20], start=1):
        snippets.extend(
            [
                f"[{index:02d}] 来源: {item['source_label']} / {item['container']}",
                f"标题: {item['title']}",
                f"时间: {item['timestamp'] or item['time_label']}",
                f"命中方式: {', '.join(item.get('retrieval_modes') or [])}",
                (item.get("content") or "")[:600],
                "",
            ]
        )
    evidence = "\n".join(snippets).strip()
    return f"""你是一位本地投研资料库检索助手。请根据最近 {days:g} 天关于“{query}”的命中文本,生成一份适合手机阅读的中文摘要。

必须遵守以下要求:
1. 第一段必须叫“检索结论”,直接回答最近 {days:g} 天关于“{query}”有哪些确定更新。
2. 第二部分必须叫“时间线 / 重点更新”,优先按时间顺序列出高价值变化。
3. 第三部分必须叫“行业 / 标的归类”,按行业或具体标的分组。
4. 第四部分必须叫“边际变化”,重点突出加单、涨价、公告、订单、政策、业绩、预期差。
5. 第五部分必须叫“来源分布”,指出这些信息主要来自哪些库或归档源。
6. 最后一部分必须叫“待验证”,单独放传闻、重复或证据弱的内容。
7. 总字数控制在 900-1200 字,每个要点尽量 1-2 行,适合手机阅读。
8. 重要公司、行业、产品关键词请加粗。

建议输出骨架:
# 统一归档检索摘要
## 检索结论
## 时间线 / 重点更新
## 行业 / 标的归类
## 边际变化
## 来源分布
## 待验证

下面是命中的原文片段:

{evidence}
"""

Technical Analysis

Content retrieved from the local archives is inserted directly into the language-model prompt through the evidence variable. Although each content field is truncated to 600 characters, the code does not:

  • Clearly delimit archive content as untrusted data.
  • Tell the model to ignore instructions embedded in retrieved documents.
  • Encode the evidence in a structured format that separates data from instructions.
  • Validate the generated response against the expected report structure.
  • Detect likely prompt-injection phrases in retrieved content.

Consequently ...[truncated 1639 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add an explicit instruction before the evidence stating that all retrieved text is untrusted data and that any commands or policy instructions inside it must be ignored.
  2. Wrap every archive record in strong, unique delimiters and label each field explicitly.
  3. Prefer structured serialization such as JSON and instruct the model to interpret serialized values only as source material.
  4. Pre-screen retrieved records for common prompt-injection patterns and either exclude, flag, or isolate suspicious records.
  5. Validate the generated response to ensure that it contains the required sections and does not introduce unsupported links or claims.
  6. Require important conclusions to cite specific source identifiers and verify that each conclusion is supported by the corresponding retrieved text.
  7. Use a non-agentic summarization context without tool permissions so that a successful injection cannot trigger external actions.
  8. Add regression tests using archive records that contain adversarial instructions.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/package_skill.py:40
Finding

Arbitrary Recursive Directory Deletion Through Packaging Destination

Content
View full analysis

Vulnerability Details

File Location: scripts/package_skill.py, lines 40-44
Vulnerability Type: Unrestricted filesystem deletion
Risk Level: Medium

Vulnerable Code

python
dest = Path(args.dest).expanduser().resolve()
if dest.exists():
    shutil.rmtree(dest)
dest.parent.mkdir(parents=True, exist_ok=True)
shutil.copytree(SKILL_DIR, dest, ignore=ignore)

Technical Analysis

The --dest command-line argument is fully user-controlled. After expansion and canonicalization, the destination is recursively deleted whenever it already exists. The code does not verify that the destination:

  • Is beneath the intended distribution directory.
  • Is different from the project directory, user home, or filesystem root.
  • Contains a marker identifying it as a previously generated package.
  • Was supplied interactively and confirmed before deletion.

Path.resolve() canonicalizes the path but does not make the deletion safe. An absolute path or a relative path resolving to any writable directory can still reach shutil.rmtree().

Attack Path

  1. An attacker influences a build command, CI parameter, wrapper script, or operator-provided --dest value.
  2. The supplied path identifies an existing directory containing valuable data.
  3. Path.expanduser().resolve() converts the value to its canonical absolute path.
  4. Because the directory exists, shutil.rmtree(dest) recursively deletes it.
  5. The script then attempts to recreate the path and copy the skill into it, potentially obscuring the original deletion.

A representative unsafe invocation would point --dest at an existing writable project or data directory. Exploitation does not require shell metacharacters because deletion is an intended operation applied to an insufficiently constrained path.

Impact Assessment

Exploitation permits recursive deletion of any directory writable by the account running the packaging script. Under ...[truncated 420 chars]

Remediation
View remediation

Remediation Suggestions

  1. Define a dedicated, fixed distribution root and require the resolved destination to be a strict descendant of that root.
  2. Reject dangerous destinations, including the filesystem root, user home, project root, skill directory, and the distribution root itself.
  3. Use Path.relative_to() or an equivalent containment check after resolving both the approved root and destination.
  4. Create a package marker file in generated directories and only allow automatic deletion when that marker is present.
  5. Require explicit confirmation or a separate --force option before deleting a non-default destination.
  6. Refuse symlink destinations and recheck containment immediately before deletion to reduce path-substitution risks.
  7. Prefer creating a new uniquely named staging directory and atomically replacing only a known prior package directory.
  8. Add tests covering paths such as /, the home directory, the project root, parent-directory traversal, and symlinked destinations.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the implementation actually packages and publishes a skill through external CLI/subprocess calls, that is a major trust-boundary violation relative to the stated archive-query purpose. Such behavior can exfiltrate artifacts, alter published content, or trigger unintended external actions while appearing to be a local-only search helper.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

If the implementation actually packages and publishes a skill through external CLI/subprocess calls, that is a major trust-boundary violation relative to the stated archive-query purpose. Such behavior can exfiltrate artifacts, alter published content, or trigger unintended external actions while appearing to be a local-only search helper.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

If the implementation actually packages and publishes a skill through external CLI/subprocess calls, that is a major trust-boundary violation relative to the stated archive-query purpose. Such behavior can exfiltrate artifacts, alter published content, or trigger unintended external actions while appearing to be a local-only search helper.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises executable shell commands and writes output files, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where an agent may invoke shell, access environment state, or write files beyond what reviewers and users would expect from the manifest alone.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description and body are written entirely in Chinese, and the skill specifies outputs such as a mobile-readable summary without indicating that the user can choose another language. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy violation unless the constraint is documented and justified.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes a skill for querying local research archives, but this file implements release automation: packaging the skill, locating a ClawHub CLI, and publishing artifacts via an external tool. Those capabilities are not part of performing archive queries and are unjustified by the stated end-user purpose of the skill itself.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The default value for --name is hard-coded as Chinese text (本地研究资料查询), which imposes a specific language choice unless the user explicitly overrides it. This is a natural-language locale policy concern because the script does not present a language choice or document a justified region-specific requirement.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/publish_skill.py (reported line 45)May include surrounding context.

python
def run_command(cmd: list[str]) -> None:
    subprocess.run(cmd, check=True)


def resolve_clawhub_bin() -> str | None:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file imports and relies on an AI analysis capability from another skill path, introducing cross-skill data flow and a broader trust boundary than the stated archive-search purpose suggests. If the AI analysis backend is remote or differently permissioned, retrieved archive content may be exposed to an external service or subsystem without obvious user awareness.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/unified_query.py (reported line 41)May include surrounding context.

python
def run_json_command(command: list[str]) -> Any:
    result = subprocess.run(command, capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError(result.stderr.strip() or result.stdout.strip() or "command failed")
    return json.loads(result.stdout or "null")

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The natural-language prompt explicitly instructs the model to generate a Chinese summary and uses Chinese-only section requirements. This imposes a fixed language on all users without opt-in or any documented reason that the skill is restricted to a Chinese-language context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill is presented as a unified local archive query tool, but it also generates and persists AI-written reports derived from retrieved content. That expands data handling beyond search into secondary processing and storage, which can expose sensitive archive content to additional components and create unexpected retention of summarized private or proprietary information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Retrieved archive content is assembled into a prompt and sent to run_ai_analysis without any user-facing warning, consent gate, or sensitivity filter. In the context of a local research archive that may include proprietary or private material, undisclosed forwarding of content to an AI analysis component creates a meaningful confidentiality and data-governance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file presents the skill name and description in Chinese, but the default prompt is hardcoded in English. This can impose a language choice on users or downstream agent behavior without an explicit opt-in or documented locale policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The fallback title 未命名资料 forces a specific language when no title is present. Under the language/locale policy, hard-coded language behavior without user opt-in can be a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.