Back to skill

Security audit

Skill Publish Tool

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent publishing helper, but its publishing script can execute injected shell commands and can push unrelated repository files without enough scoping or confirmation.

Review this skill carefully before installing. Use only with a clean, dedicated skill repository, prefer --skip-git and --skip-clawhub until you inspect the generated changes, do not pass untrusted changelog or slug values, avoid the documented force-push and global credential-store advice, and pin/verify the ClawHub CLI instead of relying on @latest.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish_skill.py:21
Finding

Shell Command Injection Through User-Controlled CLI Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/publish_skill.py, lines 21-29, 145-147, and 162-167
Vulnerability Type: OS command injection through unsafe shell command construction
Risk Level: Critical

Vulnerable Code

python
def run_cmd(cmd, cwd=None):
    """执行 shell 命令"""
    print(f"🔧 执行:{cmd}")
    result = subprocess.run(cmd, shell=True, cwd=cwd, capture_output=True, text=True)
    if result.stdout:
        print(result.stdout.strip())
    if result.returncode != 0 and result.stderr:
        print(f"❌ 错误:{result.stderr.strip()}")
    return result.returncode == 0, result.stdout, result.stderr
python
# 提交
commit_msg = f"v{version}: {message}"
success, _, _ = run_cmd(f'git commit -m "{commit_msg}"', cwd=git_cwd)
python
def publish_to_clawhub(cwd, slug, version, changelog):
    """发布到 ClawHub"""
    print(f"🚀 发布到 ClawHub: {slug}@{version}")

    cmd = f"npx clawhub@latest publish {cwd} --slug {slug} --version {version} --changelog \"{changelog}\""
    success, output, stderr = run_cmd(cmd)

Technical Analysis

The run_cmd function invokes subprocess.run with shell=True. The --changelog and --slug command-line arguments, as well as the resolved Skill path, are interpolated directly into shell command strings.

The changelog is enclosed in double quotes, but this is not adequate shell escaping. An attacker can include a double quote followed by shell operators, command substitutions, redirects, or separators. The same changelog value reaches both the Git commit command and the ClawHub publication command.

The slug and path are also not validated or safely encoded. Although a path must identify an existing directory, directory names can contain shell metacharacters.

Attack Path

  1. An attacker convinces a user or automated workflow to publish a Skill using an attacker-controlled changelog, slug, or directory path.
  2. The attacker ...[truncated 1267 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove shell=True and represent every command as an argument list:

    python
    def run_cmd(args, cwd=None):
        return subprocess.run(
            args,
            shell=False,
            cwd=cwd,
            capture_output=True,
            text=True,
            check=False,
        )
    
  2. Invoke Git without constructing a shell command:

    python
    commit_msg = f"v{version}: {message}"
    run_cmd(["git", "commit", "-m", commit_msg], cwd=git_cwd)
    
  3. Invoke ClawHub with separate arguments:

    python
    run_cmd([
        "npx",
        "clawhub@PINNED_VERSION",
        "publish",
        cwd,
        "--slug",
        slug,
        "--version",
        version,
        "--changelog",
        changelog,
    ])
    
  4. Validate slugs against an explicit allowlist pattern, such as lowercase letters, digits, and hyphens.

  5. Validate versions using a fully anchored semantic-version pattern.

  6. Resolve and validate filesystem paths before use.

  7. Add regression tests using quotes, semicolons, command substitutions, newlines, and leading option characters in every user-controlled argument.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/publish_skill.py:129
Finding

Unbounded Git Staging and Push Can Publish Unrelated Sensitive Files

Content
View full analysis

Vulnerability Details

File Location: scripts/publish_skill.py, lines 129-158 and 245-251
Vulnerability Type: Excessive repository access and unintended data publication
Risk Level: High

Vulnerable Code

python
def git_commit_push(cwd, version, message, collection_root=None):
    """提交并推送代码"""
    # 如果是集合仓库,使用集合根目录作为 Git 仓库
    git_cwd = collection_root if collection_root else cwd

    # 添加所有文件
    success, _, _ = run_cmd("git add -A", cwd=git_cwd)
    if not success:
        return False

    # 检查是否有更改
    success, output, _ = run_cmd("git status --porcelain", cwd=git_cwd)
    if not output.strip():
        print("ℹ️  没有文件更改")
        return True

    # 提交
    commit_msg = f"v{version}: {message}"
    success, _, _ = run_cmd(f'git commit -m "{commit_msg}"', cwd=git_cwd)
    if not success:
        return False

    # 推送
    success, _, stderr = run_cmd("git push", cwd=git_cwd)
    if not success:
        if "could not read Username" in stderr or "Authentication failed" in stderr:
            print("⚠️  Git 认证失败,请配置 Git 凭证或 SSH 密钥")
        else:
            print("⚠️  推送失败,请检查远程仓库配置")
        return True  # 不视为致命错误
python
# 3. Git 提交和推送
if not args.skip_git:
    print("\n━━━ 步骤 3: Git 提交和推送 ━━━")
    # 如果是集合仓库,使用集合根目录
    git_root = args.collection_root if args.collection_root else skill_path
    init_git(git_root)
    git_commit_push(skill_path, new_version, args.changelog, git_root)

Technical Analysis

The optional --collection-root value is accepted as an arbitrary working directory without verifying that it is the correct Git repository or that the target Skill is contained within it. The function then executes git add -A from that directory.

git add -A stages all tracked modifications, deletions, and untracked files throughout the selected repository. It is not limited to package.json, _meta.json, and README.md, whic ...[truncated 1742 chars]

Remediation
View remediation

Remediation Suggestions

  1. Resolve skill_path and collection_root with os.path.realpath and verify that the Skill directory is contained within the selected repository.

  2. Use git rev-parse --show-toplevel to identify the actual repository root instead of trusting an arbitrary path.

  3. Stage only files intentionally modified by the tool:

    python
    files = [
        os.path.join(skill_path, "package.json"),
        os.path.join(skill_path, "_meta.json"),
        os.path.join(skill_path, "README.md"),
    ]
    subprocess.run(["git", "add", "--", *files], cwd=git_root, check=True)
    
  4. Reject paths outside the verified repository and account for symbolic-link traversal.

  5. Display git diff --cached --name-status and require explicit confirmation before committing or pushing in interactive use.

  6. In automation, support an explicit allowlist of files and fail if any additional file becomes staged.

  7. Scan staged content for common secret formats before committing.

  8. Verify and display the exact remote URL and branch before push.

  9. Treat push failures as failures rather than returning success, so automation cannot report a misleading successful publication state.

T08 · Insecure Dependencies

Warning
Location
scripts/publish_skill.py:166
Finding

Mutable and Inconsistently Named npm Package Is Downloaded and Executed

Content
View full analysis

Vulnerability Details

File Location: scripts/publish_skill.py, line 166; README.md, lines 15-17; USAGE.md, lines 5-8
Vulnerability Type: Unpinned dependency execution and package-name confusion
Risk Level: Medium

Vulnerable Code

python
cmd = f"npx clawhub@latest publish {cwd} --slug {slug} --version {version} --changelog \"{changelog}\""
bash
# 安装 skill(如果是从 ClawHub 安装)
npx clawhub@latest install skill-publisher
bash
npx clawhub@latest install skill-publish-tool

Technical Analysis

The publication path invokes npx clawhub@latest. The latest tag is mutable and may resolve to different package content on each run. When the package is not already available locally, npx can download and execute package code without that code being part of the audited project.

The README also tells users to install skill-publisher, while the package name, metadata slug, and other documentation identify the project as skill-publish-tool. This inconsistency introduces name-confusion risk and may direct users to a different artifact.

There is no lockfile, exact ClawHub CLI version, integrity verification, or package-identity validation in the audited project.

Attack Path

  1. A user invokes the publishing script or follows the installation documentation.
  2. npx resolves the mutable latest release of the ClawHub package.
  3. If a future upstream release or distribution account is compromised, attacker-controlled package code is downloaded and executed.
  4. Alternatively, a user follows the README’s inconsistent skill-publisher instruction and installs an unintended Skill.
  5. The downloaded code runs with the privileges and credentials of the user or CI runner.

This finding does not establish that the current ClawHub package or the differently named Skill is malicious. The risk arises from mutable resolution and inconsistent identity.

Impact Assessment

A ...[truncated 450 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin the ClawHub CLI to a specific audited version instead of using @latest.
  2. Declare the CLI as a development dependency and commit a lockfile with integrity metadata.
  3. Use a locked installation mechanism such as npm ci in CI/CD.
  4. Review release provenance and use npm provenance or signature verification where supported.
  5. Correct the README command so the Skill identifier consistently matches skill-publish-tool.
  6. Centralize package and Skill identifiers so documentation and code cannot diverge.
  7. Consider requiring the CLI to be preinstalled from a trusted, controlled environment rather than permitting runtime downloads.
  8. Configure CI runners with minimal, short-lived credentials to limit supply-chain impact.

T09 · Insecure Skill Coding Practices

Error
Location
USAGE.md:164
Finding

Troubleshooting Guidance Recommends Destructive Pushes and Plaintext Credential Storage

Content
View full analysis

Vulnerability Details

File Location: USAGE.md, lines 164-180
Vulnerability Type: Unsafe operational guidance for source control and credential management
Risk Level: High

Vulnerable Documentation

bash
cd <skill directory>
# Method 1: Force push (overwrite remote)
git push -u origin main --force

# Method 2: Merge remote history
git pull origin main --allow-unrelated-histories
git push -u origin main
text
- HTTPS: `git config --global credential.helper store` and then re-enter the password
- SSH: Configure an SSH key with `ssh-keygen` and add it to GitHub

Technical Analysis

The troubleshooting guide recommends git push --force as a recovery option when a remote repository has independent history. A force push can overwrite the remote branch without verifying whether another contributor has added commits since the user last fetched it.

The guide also recommends globally enabling Git’s credential.helper store. This helper commonly stores credentials unencrypted in the user’s Git credentials file. Applying it globally affects all repositories for that account and may retain long-lived authentication material beyond the immediate task.

These are documented user actions rather than commands automatically executed by the Python script, but they are presented as solutions users are expected to follow.

Attack Path

Remote history loss path:

  1. A push fails because the remote branch contains commits absent from the local branch.
  2. The user follows the documented --force instruction.
  3. Git replaces the remote branch reference with the local branch state.
  4. Remote-only commits become unreachable through the normal branch and may be lost after retention or garbage-collection periods.

Credential exposure path:

  1. Git authentication fails.
  2. The user follows the documented global credential-helper instruction.
  3. The user enters a reusable u ...[truncated 719 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove ordinary --force guidance. Prefer fetching and reviewing remote history before rebasing or merging.
  2. Where rewriting history is genuinely necessary, recommend --force-with-lease, explain its limitations, require confirmation of the target branch, and create a backup reference first.
  3. Warn users explicitly that force-pushing shared or protected branches can destroy remote history.
  4. Recommend branch protection rules that reject force pushes to primary and release branches.
  5. Replace credential.helper store guidance with operating-system-backed credential managers, such as Git Credential Manager, macOS Keychain, or an appropriate Linux secret service.
  6. Recommend short-lived, minimally scoped tokens instead of reusable passwords.
  7. Avoid modifying credential configuration globally unless there is a documented organizational requirement.
  8. Advise users who previously enabled plaintext storage to remove stored credentials, rotate affected tokens, and configure a secure helper.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (23)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · USAGE.md (reported line 161)May include surrounding context.

bash
cd <skill 目录>
git remote add origin <github-repo-url>
git push -u origin main

Q: Git 推送失败 - 远程仓库已有内容

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
70% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · USAGE.md (reported line 161)May include surrounding context.

bash
cd <skill 目录>
git remote add origin <github-repo-url>
git push -u origin main

Q: Git 推送失败 - 远程仓库已有内容

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
84% confidence
Finding

The documentation suggests git pull origin main --allow-unrelated-histories, which disables a Git safety boundary and merges unrelated histories that would normally be rejected. While not inherently malicious, it can cause users to combine the wrong repositories or conceal provenance mistakes, leading to integrity issues in the published skill repository.

Content

Scanner excerpt · USAGE.md (reported line 173)May include surrounding context.

git push -u origin main --force

方法 2: 合并远程历史

git pull origin main --allow-unrelated-histories git push -u origin main

text

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a concrete tool-parameter abuse issue: a generic shell execution primitive is exposed and later fed command strings containing user-controlled values. In a publishing skill that performs git operations and invokes npx, successful injection can tamper with repositories, exfiltrate credentials, or execute arbitrary code on the operator's machine, making the context especially dangerous.

Content

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

python
def run_cmd(cmd, cwd=None):
    """执行 shell 命令"""
    print(f"🔧 执行:{cmd}")
    result = subprocess.run(cmd, shell=True, cwd=cwd, capture_output=True, text=True)
    if result.stdout:
        print(result.stdout.strip())
    if result.returncode != 0 and result.stderr:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document advertises automatic Git commit/push and ClawHub publishing but does not prominently warn that these actions modify local files and transmit content to remote services. In a publishing skill, this can lead users or downstream agents to trigger irreversible or externally visible changes without informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The usage examples provide copy-pastable commands that update files and may publish remotely, yet they omit any warning about side effects such as version bumps, README changes, Git pushes, and marketplace releases. This increases the risk of accidental publication, unintended repository modification, or leakage of internal content when users follow the examples directly.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The report recommends npx clawhub@latest install skill-publish-tool, which pulls and executes the latest package version without pinning. This creates a supply-chain risk: a compromised or breaking upstream release could execute unexpected code on the user's machine during installation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The user-facing README is entirely in Chinese, including feature descriptions, usage scenarios, and prerequisites, with no indication that other languages are supported or that the skill is intentionally limited to a Chinese-speaking audience. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The README instructs users to run npx clawhub@latest install skill-publisher, which fetches and executes remote package code without pinning to a specific version. In a publishing tool that already automates GitHub pushes and marketplace publication, this increases supply-chain risk substantially: a compromised or malicious new release of the package could execute arbitrary code in the user's environment with access to local files, credentials, and repositories.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documentation describes capabilities to read and modify local files and execute shell commands, yet it declares no explicit tool scope or permissions boundary. That creates an authorization ambiguity where an agent may invoke powerful operations without clear least-privilege constraints, increasing the risk of unintended repository modification, credential misuse, or command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill advertises automation of version bumps, git commit/push, and ClawHub publishing, but the description does not prominently warn that it will perform external side effects against remote services. Users may invoke it expecting local changes only and unintentionally publish code or metadata, causing accidental disclosure, unauthorized releases, or irreversible repository history changes.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

Using npx clawhub without a pinned version allows whatever package version is current at execution time to be fetched and run. If the upstream package is compromised, replaced, or changed incompatibly, the skill could execute attacker-controlled code during publication with the user's local permissions and possibly access tokens.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The documentation instructs users to run npx clawhub@latest install ..., which fetches and executes the latest package version without pinning. This creates a supply-chain risk: if the upstream package is compromised or a breaking change is introduced, users may execute unintended code during installation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The guide recommends git push --force as a remedy for remote history conflicts but does not clearly warn that this can overwrite remote history and destroy collaborators' work. In a publishing automation context, users may follow copy-pasted commands quickly, increasing the chance of accidental data loss.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

This manifest description says the skill will automatically update a GitHub repository and publish a Skill to ClawHub, but it does not specify the trigger conditions, scope, or constraints for when those actions occur. Because package.json is a manifest file and the wording is high-level and automatic, it creates ambiguity about activation and could lead to unintended invocation assumptions.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

The helper executes arbitrary shell strings with shell=True, which makes every caller vulnerable to shell metacharacter injection if any part of the command is derived from user-controlled input. In this script, later commands interpolate user arguments such as slug and changelog, so the generic subprocess pattern is not merely theoretical but directly exploitable for command injection.

Content

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

python
def run_cmd(cmd, cwd=None):
    """执行 shell 命令"""
    print(f"🔧 执行:{cmd}")
    result = subprocess.run(cmd, shell=True, cwd=cwd, capture_output=True, text=True)
    if result.stdout:
        print(result.stdout.strip())
    if result.returncode != 0 and result.stderr:

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding

Using npx clawhub@latest pulls and executes the newest package version at runtime, which creates a supply-chain risk and makes behavior non-reproducible. If the upstream package is compromised or a breaking change is introduced, this script will execute unreviewed code during publishing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The publish command is constructed from untrusted CLI inputs and executed immediately without confirmation, while changelog and slug are interpolated into a shell command string. Because execution happens via shell=True, a crafted changelog or slug can break out of quoting and execute arbitrary local commands under the user's account.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language content appears to force a single language presentation for the skill documentation. Under the stated policy, a skill should offer language choice or document a justified locale-specific scope to avoid an implicit language constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The natural-language content of the skill description is entirely in Chinese, including invocation guidance and examples, with no indication that users may choose another language or that the skill is intentionally restricted to a Chinese-speaking context. Under the stated policy, forcing a specific language without opt-in can be a locale-policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file forces a single language/locale for all user-facing instructions, and there is no indication that this locale constraint is optional, user-selected, or justified by a region-specific purpose. This matches the policy category for language or locale restrictions without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The only natural-language description in the manifest is written in Chinese, with no indication that the skill supports user language choice or that the locale is intentionally limited. This can violate language/locale policy expectations when a skill appears to impose a specific language without opt-in or documented regional scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

User-facing docstrings, help text, and console messages are written in Chinese throughout the script, which imposes a specific language on users without any opt-in or stated regional justification. The policy requires flagging language or locale constraints when the skill does not offer user choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.