Back to skill

Security audit

Skill Auto Publisher

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real ClawHub publishing helper, but it can publish and modify metadata without the documented confirmation step and contains a validated local code-execution bug in its publish script.

Install only after review if you are comfortable with a publishing helper that can modify skill metadata and publish through local ClawHub credentials. Use it only on trusted skill directories, add a real confirmation or dry-run gate before publishing, and fix the python3 -c interpolation bug before processing third-party or untrusted skills.

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

Error
Location
scripts/publish.sh:77
Finding
Arbitrary Python Code Execution Through Unsafe Source Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/publish.sh:77, 88-92, 97-102` **Vulnerability Type**: Python code injection **Risk Level**: High ### Vulnerable Code ```bash CURRENT_VERSION=$(python3 -c "import json; print(json.load(open('$META_FILE')).get('version', '1.0.0'))") ``` ```bash VERSION=$(python3 -c " parts = '$CURRENT_VERSION'.split('.') parts[-1] = str(int(parts[-1]) + 1) print('.'.join(parts)) ") ``` ```bash python3 -c " import json meta = {'slug': '$SKILL_NAME', 'version': '$VERSION'} with open('$META_FILE', 'w') as f: json.dump(meta, f, indent=2) " ``` ### Technical Analysis The script constructs Python source code dynamically and passes it to `python3 -c`. Several values are placed directly inside single-quoted Python string literals without escaping: - `META_FILE` is derived from the user-selected skill directory. - `SKILL_NAME` is derived from the basename of that directory. - `CURRENT_VERSION` is read from the skill's attacker-controllable `_meta.json`. - `VERSION` can be supplied directly through the `--version` command-line argument. Shell quoting does not make these values safe within the subsequently generated Python source. A value containing a single quote can terminate its intended Python string literal. Additional syntactically valid Python statements can then be introduced into the code executed by `python3 -c`. This issue is distinct from shell command injection: the shell invokes the intended Python executable, but Python parses attacker-controlled content as executable source rather than data. ### Attack Path 1. An attacker prepares or controls a skill directory submitted to the publishing workflow. 2. The attacker places a crafted value in one of the following sources: - The skill directory path or basename. - The `version` property in `_meta.json`. - The `--version` command-line argument. 3. The crafted value contains a quote that closes the generated Python string, followed by valid Pyt ...[truncated 1545 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never interpolate paths, metadata, or command-line arguments into Python source code. Pass all values as ordinary process arguments and read them through `sys.argv`. For example, replace metadata reading with: ```bash CURRENT_VERSION=$( python3 - "$META_FILE" <<'PY' import json import sys with open(sys.argv[1], encoding="utf-8") as handle: metadata = json.load(handle) print(metadata.get("version", "1.0.0")) PY ) ``` Replace version incrementing with argument-based processing and strict validation: ```bash VERSION=$( python3 - "$CURRENT_VERSION" <<'PY' import re import sys version = sys.argv[1] if not re.fullmatch(r"(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)", version): raise SystemExit("Invalid semantic version") major, minor, patch = map(int, version.split(".")) print(f"{major}.{minor}.{patch + 1}") PY ) ``` Write `_meta.json` by passing every value separately: ```bash python3 - "$META_FILE" "$SKILL_NAME" "$VERSION" <<'PY' import json import sys meta_file, skill_name, version = sys.argv[1:] metadata = { "slug": skill_name, "version": version, } with open(meta_file, "w", encoding="utf-8") as handle: json.dump(metadata, handle, indent=2) PY ``` Additional hardening should include: 1. Validate both existing and user-supplied versions against a strict semantic-version expression before any file modification. 2. Validate `SKILL_NAME` against the same slug constraints used for published metadata, such as `^[a-z0-9-]+$`. 3. Reject missing values for `--version` and `--changelog` before shifting command-line arguments. 4. Resolve and verify the skill directory before use, and ensure it is within an approved publishing root if the workflow processes untrusted paths. 5. Run the publishing process with a dedicated, least-privileged account and narrowly scoped ClawHub credentials. 6. Add regression tests containing quotes, newlines, backslashes, and Python syntax in directory names, metadata ...[truncated 40 chars]
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents a comprehensive publishing assistant covering the entire release pipeline. The actual code chunk only implements skill-name/slug availability detection via a CLI search and alternative-name suggestions. While slug validation could be a small supporting part of a publishing workflow, this code does not show any of the core declared behaviors such as automatic version bumping, changelog generation, metadata validation broadly, confirmation, or one-click publishing. Therefore the supplied code chunk does not accurately represent the declared primary purpose and is a material mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The code broadly matches the core purpose of publishing a skill to ClawHub with automatic version increment and metadata validation. However, the description claims a fuller workflow than the code actually implements. Specifically, there is no logic for generating a changelog automatically or intelligently; the script merely accepts `--changelog` as an optional input. There is also no user confirmation step before publication—the script proceeds directly to publishing after validation and version update. Additionally, the code performs slug availability checking and publish-history recording, which are extra behaviors not reflected in the description. The most material issue is that two prominently advertised capabilities—intelligent changelog generation and user confirmation—are absent, so the description does not accurately represent the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description promises an end-to-end ClawHub publishing assistant with automated versioning, changelog generation, metadata validation, confirmation, and one-click publish behavior. The supplied code only implements local history storage and retrieval via `.publish_history.json`. It computes file hashes, records version/changelog/timestamp/snapshot metadata, and prints history. While publish-history tracking could be a supporting component of a publishing tool, this code chunk by itself does not implement the main declared workflow and lacks the central publishing capabilities. Therefore the description materially overstates what this code actually does.

Ae1

High
Category
analysis-evasion
Content
"SKILL.md": "hash:abc123",
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill documentation clearly instructs the agent to read and write files and invoke shell commands, but the manifest declares no explicit tool scope or permissions. In a publishing workflow that touches local history files and can invoke a publish script with shell arguments, missing scope boundaries increases the chance of unintended command execution or file modification beyond the intended skill directory.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The manifest advertises broad trigger words without clear exclusions, making accidental or contextually inappropriate activation more likely. Because this skill's purpose includes potentially sensitive actions like file modification and publishing, overbroad activation materially increases the chance of unintended execution.

Vague Triggers

Medium
Confidence
94% confidence
Finding
Broad triggers like '发布这个技能' or publishing the 'current skill' can cause the agent to act on an inferred target rather than an explicitly identified one. In a skill that may write files, update versions, and run publish commands, ambiguous activation increases the risk of publishing the wrong project or performing side effects in the wrong directory.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code uses Chinese-only natural-language strings in its docstrings and all user-facing console messages, such as the usage text and status/error output. That creates a locale/language policy concern because the skill imposes a specific language on users without any opt-in, fallback, or documented region-specific justification.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def check_slug_available(slug):
    """检查技能名称是否可用"""
    try:
        result = subprocess.run(
            ["skillhub", "search", slug],
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This shell script's comments, usage text, and runtime status/error messages are all presented in Chinese, including the user-facing outputs at invocation and failure points. The file does not offer any language selection, fallback, or documentation justifying a Chinese-only locale, which conflicts with the policy against forcing a specific language without user opt-in.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The script performs the irreversible publish action immediately after validation and version updates, with no interactive confirmation or dry-run safeguard. In a publishing skill, this increases the risk of accidental releases, especially because the skill metadata explicitly suggests there should be a user confirmation step, so operators may rely on a protection that does not actually exist.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
This code presents its docstrings, usage help, errors, and status messages only in Chinese, including the top-level description and all CLI output. The policy requires flagging language or locale constraints when the skill forces a specific language without user opt-in or documented justification.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This code file contains user-facing natural-language strings in Chinese, beginning with the module docstring, and all subsequent CLI output is also Chinese-only. The policy requires avoiding forced language or locale constraints unless the skill offers a choice or clearly documents a justified region-specific limitation, which is not present here.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The usage text, validation status, error labels, warning labels, and failure message are all emitted only in Chinese. Because the script does not offer user opt-in for language selection or document a justified locale restriction, it forces a specific language on users.

Static analysis

No suspicious patterns detected.