Back to skill

Security audit

Skill Install Guardian

Security checks for vulnerabilities and agentic risk

Overview

This security-checking skill is not clearly malicious, but its own checks can miss or misreport risky skills and it relies on unpinned npx execution.

Install only after review. Treat this as a helper, not a reliable gate: pin or preinstall a trusted ClawHub CLI, run it in a low-privilege environment, manually inspect upstream security reports, and do not rely on its deep scan for nested scripts or final approval.

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

Error
Location
scripts/check.py:93
Finding
Unpinned npx Package Execution Creates a Supply-Chain Code Execution Risk## Vulnerability Details **File Location**: `scripts/check.py`, line 93 **Vulnerability Type**: Unpinned executable dependency **Risk Level**: High ```python # Use list form to avoid shell injection stdout, stderr, code = run_command(["npx", "clawhub", "inspect", slug, "--json"]) ``` The same unpinned `npx clawhub` invocation pattern is also used for file inspection, searching, and listing. `SKILL.md` similarly instructs users to invoke `npx clawhub` without a pinned package version. ### Technical Analysis Invoking a package through `npx` without pinning and locally provisioning a reviewed version can cause npm to resolve and download executable package code at runtime. Avoiding `shell=True` protects against shell metacharacter injection in the slug, but it does not protect against a compromised, malicious, or unexpectedly changed npm package. npm package installation and lifecycle behavior occurs with the privileges of the user running the guardian. The subprocess also inherits the parent process environment because no restricted `env` is supplied to `subprocess.run`. Consequently, remotely resolved package code may be able to read workspace files, user configuration, npm credentials, API tokens, SSH material, and other environment variables accessible to that user. This exceeds the minimum privileges needed for a read-only scanner: the implementation needs a known ClawHub client, but it delegates execution to a potentially mutable package resolved at runtime. ### Attack Path 1. An attacker compromises the npm package, its publisher account, or another relevant dependency in its dependency graph. 2. The attacker publishes a malicious version that preserves expected CLI output while adding malicious installation or runtime behavior. 3. A user runs `scripts/check.py` on an otherwise legitimate skill. 4. `npx` resolves or downloads the unpinned package and executes attacker-controlled code. 5. The malicious package runs ...[truncated 702 chars]
Remediation
## Remediation Suggestions - Install a reviewed ClawHub CLI version ahead of time and invoke its fixed executable directly rather than allowing `npx` to download packages on demand. - Pin an exact package version and verify its integrity using a committed lockfile and npm integrity metadata. - Use `npx --no-install` or the corresponding modern npm option so the scan fails if the approved local dependency is unavailable. - Consider vendoring or packaging the reviewed client as part of a reproducible deployment. - Run the external CLI with a minimal environment rather than inheriting all environment variables. - Execute the scanner in a sandbox with read-only workspace access, no unnecessary credentials, and restricted outbound networking. - Apply the same hardening to every `npx clawhub` invocation documented in `SKILL.md` and implemented in `scripts/check.py`.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check.py:105
Finding
ClawHub Security Flags Are Ignored and Treated as a Passing Result## Vulnerability Details **File Location**: `scripts/check.py`, lines 105-110 **Vulnerability Type**: Fail-open security validation **Risk Level**: High ```python # Check for any security flags in the data if 'security' in data: return { "status": "CHECKED", "message": "Security report found", "passed": True } ``` ### Technical Analysis The code checks only whether the ClawHub response contains a `security` field. It never examines the field's contents, severity, verdict, vulnerability list, or malicious-code indicators. Any parseable response containing that key is classified as passing, including a report that explicitly marks a skill as malicious. This directly conflicts with the documented workflow in `SKILL.md`, which says that a flagged security report must cause an immediate abort. The report generator later relies on `v1['passed']`, so this unconditional `True` propagates into the overall recommendation. The `NO_REPORT` branch is also fail-open and returns `passed: True`, meaning the absence of security evidence is represented as a successful check rather than an unknown or review-required state. ### Attack Path 1. An attacker publishes a skill that has been flagged by ClawHub or otherwise receives an adverse security report. 2. The user runs the guardian against the attacker's slug. 3. ClawHub returns valid JSON containing a `security` field with a failing or malicious verdict. 4. The guardian checks only for the field's existence and sets `passed` to `True`. 5. If the incomplete local pattern scanner finds no critical regex match, the final report states that the skill can proceed. 6. The owner may install the malicious skill based on the guardian's incorrect assurance. 7. Any malicious behavior in that installed skill then executes under the privileges granted to the skill runtime. ### Impact Assessment This flaw does not itself install or execute the inspecte ...[truncated 362 chars]
Remediation
## Remediation Suggestions - Parse the documented ClawHub security-report schema and explicitly validate its verdict, severity, and findings. - Maintain a strict allowlist of passing statuses; treat unknown, missing, malformed, or newly introduced statuses as non-passing. - Fail closed when the report is unavailable or cannot be interpreted. - Include the actual upstream verdict and findings in the owner-facing report. - Add tests for clean, malicious, flagged, missing-report, malformed-response, and unknown-status cases. - Ensure the code enforces the documented “flagged means abort” policy rather than relying on owner interpretation.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check.py:233
Finding
Nested Script Paths Are Reduced to Basenames, Allowing Deep-Scan Bypass## Vulnerability Details **File Location**: `scripts/check.py`, lines 233-237 **Vulnerability Type**: Incomplete security scanning caused by incorrect path handling **Risk Level**: High ```python # For script files (.py, .js, .sh), analyze content if file.endswith(('.py', '.js', '.sh')): # Get the file name without path filename = file.split('/')[-1] content = fetch_file_content(slug, filename) ``` The relevant fetch helper forwards the supplied path to ClawHub: ```python def fetch_file_content(slug, file_path): """Fetch a single file's content from the skill.""" # Use npx to get file content stdout, stderr, code = run_command(["npx", "clawhub", "inspect", slug, "--file", file_path]) if code == 0 and stdout: return stdout return None ``` ### Technical Analysis The file listing preserves relative paths, such as `scripts/check.py`, but the analyzer strips each script path to its basename before fetching it. It therefore requests `check.py` rather than `scripts/check.py`. If ClawHub requires the listed relative path, the fetch fails and returns `None`. The caller silently skips analysis and records no error. The file is still counted in `files_scanned`, so the final message can misleadingly claim that it was deeply analyzed. The project itself uses the conventional nested `scripts/check.py` layout, making this flaw directly relevant to the files the scanner claims to inspect. Basename conversion can also create ambiguity when multiple directories contain scripts with the same name. The scanner may fetch the wrong file or fail to fetch either one, while reporting no critical finding. ### Attack Path 1. An attacker publishes a skill containing malicious code at a nested path such as `scripts/runner.py`. 2. The `--files` listing returns `scripts/runner.py`. 3. The guardian reduces this path to `runner.py`. 4. The content request for `runner.py` fails or resolves ...[truncated 925 chars]
Remediation
## Remediation Suggestions - Pass the exact relative path returned by the trusted file listing to `fetch_file_content` without reducing it to a basename. - Normalize paths using POSIX path rules and reject absolute paths, traversal components such as `..`, control characters, and malformed entries. - Treat every failed content fetch as a scan failure, not as a silently skipped file. - Track separate counters for discovered, fetched, successfully scanned, skipped, and failed files. - Require all executable or instruction-bearing files to be fetched successfully before phase two can pass. - Detect duplicate or ambiguous normalized paths. - Add tests covering nested scripts, duplicate basenames, paths with spaces, failed fetches, and malicious code under `scripts/`. - Prefer structured JSON file-list output from the CLI instead of parsing human-readable whitespace-delimited output.
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (11)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
"""Run a command and return output."""
    try:
        if use_shell:
            result = subprocess.run(
                cmd, shell=True, capture_output=True, text=True, timeout=30
            )
        else:
Confidence
90% 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).

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documents and requires capabilities equivalent to shell execution, network access, and filesystem reads, but it does not declare any explicit tool scope such as permissions or allowed-tools. For a security-sensitive installation guard, this creates a transparency and least-privilege problem: an agent may run broad commands without a machine-readable restriction boundary, increasing the chance of unintended or overbroad execution.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
Using `npx clawhub` without a pinned version allows execution of whatever package version resolves at runtime, which can change over time or be compromised upstream. In this skill, that risk is amplified because the command is part of a security-verification workflow, so a malicious or breaking update could subvert the very checks meant to protect installation.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
This unpinned `npx clawhub` invocation has the same supply-chain risk: it may fetch and execute a different package version than expected. Because this phase fetches files for code analysis, a compromised package could falsify results, hide malicious content, or run unintended code during inspection.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
The install command uses `npx clawhub` without version pinning, introducing supply-chain risk at the moment of installation. An attacker controlling or compromising the resolved package version could execute arbitrary logic or alter what gets installed, directly affecting the local environment.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
This workflow step again relies on an unpinned `npx clawhub` reference, so the behavior of a critical installation action is not stable or auditable. In the context of a 'security guardian' skill, this inconsistency undermines trust and could let a malicious upstream update bypass or weaken protections.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""Run a command and return output."""
    try:
        if use_shell:
            result = subprocess.run(
                cmd, shell=True, capture_output=True, text=True, timeout=30
            )
        else:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Use list form to avoid shell injection
            if isinstance(cmd, str):
                cmd = cmd.split()
            result = subprocess.run(
                cmd, capture_output=True, text=True, timeout=30
            )
        return result.stdout, result.stderr, result.returncode
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Rp1

Medium
Category
MCP Rug Pull
Confidence
86% confidence
Finding
The script repeatedly executes 'npx clawhub ...' without pinning a specific package version or otherwise establishing trust for the resolved package. That creates a supply-chain risk: a malicious or compromised package version could be fetched and executed at runtime, undermining the very security check this skill is supposed to provide.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The advertised 'DEEP content analysis' is incomplete: nested script files are enumerated, but content fetches use only the basename, which can miss files in subdirectories or analyze the wrong file if names collide. This creates a false sense of safety and allows malicious code to evade scanning by being placed in nested paths, which is especially dangerous in a security-review skill.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The skill claims to require owner confirmation before installation, but the implementation only prints a warning and returns a proceed/fail status. In automated or chained workflows, downstream tooling may treat a successful exit as authorization to continue, creating a security control bypass through misleading UX and unmet policy guarantees.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/check.py:17