Back to skill

Security audit

Clawhub Rate Limited Publisher Fixed

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent publishing purpose, but its helper script turns queue entries into broad shell commands that can run more than just ClawHub publishing.

Review before installing. Use only queue files you created and trust, avoid the optional command field, and do not schedule this helper until the uploader is changed to call a fixed argument list such as clawhub publish <path> with shell=False and protected state updates.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/clawhub_rate_limited_uploader.py:56
Finding

Arbitrary Command Execution Through Unsafe Queue Command Processing

Content
View full analysis
List[QueueItem]: items = queue_data.get("items") if not isinstance(items, list): raise SystemExit('Queue JSON must contain an "items" array.') normalized: List[QueueItem] = [] for index, item in enumerate(items): if not isinstance(item, dict): raise SystemExit(f"Queue item #{index} must be an object.") path = item.get("path") if not isinstance(path, str) or not path.strip(): raise SystemExit(f'Queue item #{index} missing non-empty "path".') command = item.get("command", DEFAULT_COMMAND) if not isinstance(command, str) or "{path}" not in command: raise SystemExit(f'Queue item #{index} has invalid "command"; it must be a string containing "{{path}}".') normalized.append(QueueItem(path=path, command=command)) return normalized def ensure_skill_dir(path_str: str) -> Path: path = Path(path_str).expanduser().resolve() if not path.exists(): raise SystemExit(f"Skill path does not exist: {path}") if not path.is_dir(): raise SystemExit(f"Skill path is not a directory: {path}") if not (path / "SKILL.md").exists(): raise SystemExit(f"Skill directory does not contain SKILL.md: {path}") return path def run_publish(item: QueueItem, execute: bool) -> subprocess.CompletedProcess[str] | None: skill_path = ensure_skill_dir(item.path) command_str = item.command.format(path=str(skill_path)) print(f"[info] command: {command_str}") if not execute: return None return subprocess.run( command_str, shell=True, text=True, capture_output=True, chec ...[truncated 3196 chars]
Remediation
View remediation
subprocess.CompletedProcess[str] | None: skill_path = ensure_skill_dir(item.path) command = ["clawhub", "publish", str(skill_path)] print(f"[info] command: {shlex.join(command)}") if not execute: return None return subprocess.run( command, shell=False, text=True, capture_output=True, check=False, cwd=str(skill_path.parent), ) ``` Additional hardening should include: 1. Remove the `command` property from the queue schema if the only supported operation is publishing. 2. If customization is essential, represent commands as JSON argument arrays rather than shell strings. 3. Strictly allowlist the executable and operation, such as exactly `clawhub` followed by `publish`. 4. Never pass queue-controlled input to `shell=True`. 5. Treat displayed commands as logs only; use `shlex.join()` for readable output rather than for execution. 6. Reject unexpected queue fields or document and validate a strict schema. 7. Add tests using paths and command values containing quotes, semicolons, substitutions, spaces, and redirection characters to confirm they remain single literal arguments. 8. Restrict queue-file ownership and permissions as defense in depth, while not relying on permissions as a replacement for safe process invocation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/clawhub_rate_limited_uploader.py:126
Finding

Rolling Rate Limit Can Be Bypassed by Concurrent Uploader Processes

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • 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
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill claims a constrained rate-limited ClawHub publishing workflow, but it also permits arbitrary per-item command templates containing {path}, effectively turning queue entries into shell execution inputs. That mismatch is dangerous because users may trust the skill as a narrowly scoped publisher while an attacker-controlled or malformed queue file can trigger execution of unintended commands under the host's local privileges.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 19)May include surrounding context.

md
1. Verify the skill folder exists and contains `SKILL.md`.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill's stated purpose is rate-limited publication of local skills, but the implementation allows the queue to supply any templated shell command containing {path}. That design lets an attacker who can modify the queue file turn a publish workflow into a general-purpose command runner, expanding the capability far beyond the documented and expected boundary.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

Using subprocess.run with shell=True on a string influenced by queue data is a classic command-injection sink. Even if {path} is populated from a validated directory path, the queue-controlled command template itself can embed additional shell operations, causing execution of unintended commands under the privileges of the publishing process.

Content

Scanner excerpt · scripts/clawhub_rate_limited_uploader.py (reported line 101)May include surrounding context.

python
print(f"[info] command: {command_str}")
    if not execute:
        return None
    return subprocess.run(
        command_str,
        shell=True,
        text=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The primary skill description is written in Chinese and the document does not provide an English alternative, user language selection, or any note that the skill is intentionally region-specific. This can violate language/locale policy because it imposes a specific language on users without opt-in.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill instructs the host to run a local Python helper, build/update a queue file, and use scheduler-driven execution, which implies shell, file read, and file write capabilities without declaring any explicit tool scope or permission boundaries. In practice, this can cause the agent or host integration to grant broader execution authority than reviewers expect, increasing the risk of unintended command execution or file modification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation and feature description suggest a safe, purpose-specific publisher, but the actual queue schema includes a free-form command field that can execute arbitrary shell commands. This mismatch increases operator trust and the chance of unsafe deployment because reviewers may assume the tool only publishes skills when it actually provides broader execution capability.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

The script builds a shell command from queue-controlled data and executes it with shell=True, which allows arbitrary shell metacharacters or an entirely different command to run. Because the queue format explicitly permits a per-item command template, this is not limited to publishing and becomes arbitrary command execution on the host running the scheduler.

Content

Scanner excerpt · scripts/clawhub_rate_limited_uploader.py (reported line 101)May include surrounding context.

python
print(f"[info] command: {command_str}")
    if not execute:
        return None
    return subprocess.run(
        command_str,
        shell=True,
        text=True,

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file presents all substantive instructions and checklist items in Chinese, but does not indicate that the user can choose another language or that the locale is intentionally constrained. The policy requires flagging language or locale constraints when a specific language is effectively forced without user opt-in.

Content

No source excerpt is available for this finding.