Back to skill

Security audit

ClawGuard

Security checks for vulnerabilities and agentic risk

Overview

This is a local skill-security scanner, but its safety claims are stronger than its actual checks, so users should review it before relying on it.

Install only if you treat ClawGuard as a local heuristic scanner, not as a definitive safety approval. It appears read-only and local, but its PASS result can miss issues and its packaged script path should be corrected or verified before use.

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

T09 · Insecure Skill Coding Practices

Error
Location
scan.py:251
Finding

Inconsistent Script Discovery Omits Root-Level and Supported Script Files from Security Checks

Content
View full analysis

Vulnerability Details

File Location: scan.py:251-269 and scan.py:330-362
Vulnerability Type: Incomplete security validation and false-negative scanning
Risk Level: High

Vulnerable Code

python
# Extract all URLs from scripts
scripts_dir = skill_dir / "scripts"
script_urls = set()

if scripts_dir.exists():
    for f in scripts_dir.rglob("*"):
        if f.suffix in {".sh", ".bash", ".py"} and f.is_file():
            try:
                script_content = f.read_text(errors="replace")
                urls = re.findall(r'https?://([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})', script_content)
                for domain in urls:
                    # Filter out github/known safe infra
                    if domain not in {"github.com", "raw.githubusercontent.com", "api.anthropic.com"}:
                        script_urls.add(domain)
            except Exception:
                pass
python
def check_permissions(skill_dir: Path, result: ScanResult):
    """Look for sensitive file access not reflected in declared permissions."""
    sensitive_paths = [
        (r"~/\.ssh|/\.ssh/", "SSH keys access"),
        (r"~/\.aws|/\.aws/", "AWS credentials access"),
        (r"~/\.config/.*token|~/\.config/.*secret", "Token/secret config access"),
        (r"/etc/passwd|/etc/shadow", "System password file access"),
        (r"~/Library/Keychains", "macOS Keychain access"),
        (r"wallet\.(dat|json)|keystore", "Crypto wallet access"),
    ]

    scripts_dir = skill_dir / "scripts"
    if not scripts_dir.exists():
        return

    found_sensitive = False
    for f in scripts_dir.rglob("*"):
        if f.suffix in {".sh", ".bash", ".py"} and f.is_file():
            try:
                content = f.read_text(errors="replace")
                rel_path = str(f.relative_to(skill_dir))
                for i, line in enumerate(content.splitlines(), 1):
                    # S
...[truncated 3296 chars]
Remediation
View remediation

Remediation Suggestions

  • Implement one canonical script-discovery function and reuse it in every check.
  • Include root-level files and recursively discovered files under scripts/.
  • Apply the same supported-extension set—.sh, .bash, .py, .rb, .js, and .ts—to all relevant checks.
  • Do not silently return a successful result when scripts/ is absent; continue scanning eligible root-level files.
  • Track which checks were applied to each discovered file and report coverage in the final output.
  • Add regression tests containing sensitive access and undeclared endpoints in every supported extension and location.
  • Treat incomplete coverage as a warning or failure rather than emitting a PASS verdict.

T09 · Insecure Skill Coding Practices

Error
Location
scan.py:157
Finding

Silent File-Read Failures Allow Incomplete Scans to Produce Trusted Verdicts

Content
View full analysis

Vulnerability Details

File Location: scan.py:157-160, scan.py:264-265, and scan.py:361-362
Vulnerability Type: Fail-open error handling
Risk Level: High

Vulnerable Code

python
try:
    content = script_path.read_text(errors="replace")
    lines = content.splitlines()
except Exception:
    continue
python
try:
    script_content = f.read_text(errors="replace")
    urls = re.findall(r'https?://([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})', script_content)
    for domain in urls:
        # Filter out github/known safe infra
        if domain not in {"github.com", "raw.githubusercontent.com", "api.anthropic.com"}:
            script_urls.add(domain)
except Exception:
    pass
python
try:
    content = f.read_text(errors="replace")
    rel_path = str(f.relative_to(skill_dir))
    for i, line in enumerate(content.splitlines(), 1):
        # Skip detection pattern lines
        if "# nocheck" in line or "# DETECTION_PATTERN" in line:
            continue
        if re.match(r'^\s*\(r[\'"]', line) or re.match(r'^\s*r[\'"].*[\'"],\s*[\'"]', line):
            continue
        for pattern, label in sensitive_paths:
            if re.search(pattern, line, re.IGNORECASE):
                result.findings.append(Finding(
                    severity="CRITICAL",
                    check="Sensitive File Access",
                    message=f"{label} detected — verify this is intentional and declared",
                    file=rel_path
                ))
                found_sensitive = True
except Exception:
    pass

Technical Analysis

Security scanners must distinguish between a clean result and an incomplete result. Here, broad except Exception handlers suppress every read or processing failure and either continue scanning or silently return from the affected operation.

The suppressed failure is not added to result.findings, does not m ...[truncated 1766 chars]

Remediation
View remediation

Remediation Suggestions

  • Replace broad, silent exception handlers with explicit handling for expected I/O and decoding errors.
  • Add a finding for every file that cannot be fully inspected, including its relative path and the sanitized error type.
  • Add an incomplete_scan state to ScanResult.
  • Prevent PASS whenever an eligible file was skipped or only partially processed.
  • Return a nonzero exit status for incomplete scans in both normal and CI modes.
  • Avoid exposing sensitive absolute paths or raw exception content in reports intended for untrusted recipients.
  • Add tests for unreadable files, broken links, disappearing files, traversal errors, and malformed filesystem entries.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:81
Finding

Security Documentation Claims Checks That Are Not Implemented

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:81-94 and scan.py:410-412
Vulnerability Type: Misleading security assurance and unsafe trust decision
Risk Level: Medium

Vulnerable Documentation and Code

text
### 4. 🟡 Permission Mismatch
Compares permissions declared in SKILL.md frontmatter against what scripts actually access. A skill that declares `env: []` but reads `$HOME/.ssh/` is a red flag.

### 5. 🟡 External Endpoint Audit
Extracts every URL and domain contacted in scripts. Cross-references against the External Endpoints table in SKILL.md. Flags undeclared endpoints.

### 6. 🟡 Repository Trust Score
Evaluates: GitHub account age (must be 7+ days), repo star count, commit history depth, number of contributors, and time since last commit.

### 7. 🟢 Structure Compliance
Verifies the skill follows the ClawHub spec: valid SKILL.md frontmatter, correct `clawdbot` metadata key (not `openclaw`), semver version, and declared `files` field.
python
if verdict == "PASS":
    lines.append("  This skill passed all critical checks. Safe to install.")
    if result.findings:
        lines.append("  Review the minor findings above at your discretion.")

Technical Analysis

The implementation does not provide the complete checks described by the Skill documentation:

  • check_permissions() searches selected scripts for fixed sensitive-path patterns, but it does not parse and compare declared frontmatter permissions against all observed file, environment, or capability access.
  • No repository trust-score check exists. The scanner does not evaluate account age, stars, commit history, contributor count, or last-commit time.
  • Endpoint auditing is narrower than documented because it only processes selected extensions under scripts/.
  • Structure validation does not comprehensively validate frontmatter or enforce the declared files field as described.

Despite these missing o ...[truncated 1331 chars]

Remediation
View remediation

Remediation Suggestions

  • Implement every advertised check or remove the unsupported claims from SKILL.md and README.md.
  • Parse frontmatter permissions and compare them against consistently collected evidence from all supported files.
  • If repository trust analysis is intentionally excluded because the tool is local-only and network-free, state that explicitly instead of claiming it is evaluated.
  • Report each check as passed, failed, not implemented, not applicable, or incomplete.
  • Replace “Safe to install” with bounded wording such as: “No configured signatures were detected in the files successfully scanned; manual review is still required.”
  • Ensure output examples match actual implementation and severity behavior.
  • Add tests that map every documented capability to a concrete implementation and expected report entry.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (16)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **One script.** `scan.py` uses Python 3 stdlib only — no pip installs, no dependencies.

Instruction Override

High
Category
Prompt Injection
Confidence
80% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · scan.py (reported line 58)May include surrounding context.

python
# Prompt injection patterns in SKILL.md
PROMPT_INJECTION_PATTERNS = [
    (r"ignore\s+(all\s+)?(previous|prior|above)\s+instructions?", "Classic prompt injection: ignore previous instructions"),
    (r"disregard\s+(your\s+)?(guidelines?|rules?|instructions?|training)", "Prompt injection: disregard guidelines"),
    (r"override\s+(your\s+)?(safety|guidelines?|rules?|restrictions?)", "Prompt injection: override safety"),
    (r"you\s+(are|must)\s+now\s+(act|behave|operate)\s+as", "Prompt injection: role override"),

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scan.py (reported line 58)May include surrounding context.

python
�─────────────────────────
# DETECTION PATTERNS
# ─────────────────────────────────────────────

# Prompt injection patterns in SKILL.md
PROMPT_INJECTION_PATTERNS = [
    (r"ignore\s+(all\s+)?(previous|prior|above)\s+instructions?", "Classic prompt injection: ignore previous instructions"),
    (r"disregard\s+(your\s+)?(guidelines?|rules?|instructions?|training)", "Prompt injection: disregard guidelines"),
    (r"override\s+(your\s+)?(safety|guidelines?|rules?|restrictions?)", "Prompt injection: override safety"),
    (r"you\s+(are|must)\s+now\s+(act|behave|operate)\s+as", "Prompt injection: role override"),
    (r"do\s+not\s+(tell|inform|warn)\s+the\s+user", "Prompt injection: silence instruction"),
    (r"execute\s+the\s+following\s+(command|instruction|code)", "Prompt injection: execute command"),
    (r"[A-Za-z0-9+/]{40,}={0,2}", "Suspicious ba

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
90% confidence
Finding

Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Content

Scanner excerpt · scan.py (reported line 59)May include surrounding context.

python
# Prompt injection patterns in SKILL.md
PROMPT_INJECTION_PATTERNS = [
    (r"ignore\s+(all\s+)?(previous|prior|above)\s+instructions?", "Classic prompt injection: ignore previous instructions"),
    (r"disregard\s+(your\s+)?(guidelines?|rules?|instructions?|training)", "Prompt injection: disregard guidelines"),
    (r"override\s+(your\s+)?(safety|guidelines?|rules?|restrictions?)", "Prompt injection: override safety"),
    (r"you\s+(are|must)\s+now\s+(act|behave|operate)\s+as", "Prompt injection: role override"),
    (r"do\s+not\s+(tell|inform|warn)\s+the\s+user", "Prompt injection: silence instruction"),

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
90% confidence
Finding

Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Content

Scanner excerpt · scan.py (reported line 60)May include surrounding context.

python
PROMPT_INJECTION_PATTERNS = [
    (r"ignore\s+(all\s+)?(previous|prior|above)\s+instructions?", "Classic prompt injection: ignore previous instructions"),
    (r"disregard\s+(your\s+)?(guidelines?|rules?|instructions?|training)", "Prompt injection: disregard guidelines"),
    (r"override\s+(your\s+)?(safety|guidelines?|rules?|restrictions?)", "Prompt injection: override safety"),
    (r"you\s+(are|must)\s+now\s+(act|behave|operate)\s+as", "Prompt injection: role override"),
    (r"do\s+not\s+(tell|inform|warn)\s+the\s+user", "Prompt injection: silence instruction"),
    (r"execute\s+the\s+following\s+(command|instruction|code)", "Prompt injection: execute command"),

Instruction Override

High
Category
Prompt Injection
Confidence
90% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · scan.py (reported line 60)May include surrounding context.

python
PROMPT_INJECTION_PATTERNS = [
    (r"ignore\s+(all\s+)?(previous|prior|above)\s+instructions?", "Classic prompt injection: ignore previous instructions"),
    (r"disregard\s+(your\s+)?(guidelines?|rules?|instructions?|training)", "Prompt injection: disregard guidelines"),
    (r"override\s+(your\s+)?(safety|guidelines?|rules?|restrictions?)", "Prompt injection: override safety"),
    (r"you\s+(are|must)\s+now\s+(act|behave|operate)\s+as", "Prompt injection: role override"),
    (r"do\s+not\s+(tell|inform|warn)\s+the\s+user", "Prompt injection: silence instruction"),
    (r"execute\s+the\s+following\s+(command|instruction|code)", "Prompt injection: execute command"),

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scan.py (reported line 65)May include surrounding context.

python
afety"),
    (r"you\s+(are|must)\s+now\s+(act|behave|operate)\s+as", "Prompt injection: role override"),
    (r"do\s+not\s+(tell|inform|warn)\s+the\s+user", "Prompt injection: silence instruction"),
    (r"execute\s+the\s+following\s+(command|instruction|code)", "Prompt injection: execute command"),
    (r"[A-Za-z0-9+/]{40,}={0,2}", "Suspicious base64 string — possible encoded payload"),
    (r"<!--.*?(ignore|override|inject).*?-->", "Hidden HTML comment with injection keyword"),
]

# Data exfiltration / reverse shell patterns in scripts
CRITICAL_SCRIPT_PATTERNS = [
    (r"bash\s+-i\s*>&?\s*/dev/tcp/", "Reverse shell: bash TCP redirect"),
    (r"nc\s+(-[a-z]+\s+)*-e\s+/bin/(bash|sh)", "Reverse shell: netcat with shell"),
    (r"python\s*-c\s*['\"]import\s+socket", "Reverse shell: python socket"),
    (r"/dev/tcp/[0-9a-zA-Z.-]+/[0-9]+", "Reverse shell: /dev/tcp pattern"),
    (r"mkfifo\s+.+\|.+(nc|netcat|ncat)", "Reverse shell: mkfifo pipe"),
    (r"curl\s+.*(--upload-file|-T|-d\s+@)\

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scan.py (reported line 78)May include surrounding context.

python
(r"curl\s+.*(--upload-file|-T|-d\s+@)\s*[~$]", "Data exfiltration: curl upload of local files"),
    (r"curl\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys|known_hosts)", "Credential theft: accessing sensitive files"),
    (r"wget\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys)", "Credential theft: wget sensitive files"),
    (r"cat\s+(~/\.ssh|~/.aws|/etc/passwd|/etc/shadow)", "Credential theft: reading system credentials"),
    (r"eval\s*\(\s*base64\s*-d", "Obfuscated execution: eval base64 decode"),
    (r'\$\(.*base64.*-d.*\)', "Obfuscated execution: command substitution with base64"),
    (r"curl\s+http[s]?://[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", "Raw IP address curl — suspicious"),

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scan.py (reported line 339)May include surrounding context.

python
(r"curl\s+.*(--upload-file|-T|-d\s+@)\s*[~$]", "Data exfiltration: curl upload of local files"),
    (r"curl\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys|known_hosts)", "Credential theft: accessing sensitive files"),
    (r"wget\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys)", "Credential theft: wget sensitive files"),
    (r"cat\s+(~/\.ssh|~/.aws|/etc/passwd|/etc/shadow)", "Credential theft: reading system credentials"),
    (r"eval\s*\(\s*base64\s*-d", "Obfuscated execution: eval base64 decode"),
    (r'\$\(.*base64.*-d.*\)', "Obfuscated execution: command substitution with base64"),
    (r"curl\s+http[s]?://[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", "Raw IP address curl — suspicious"),

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scan.py (reported line 78)May include surrounding context.

python
(r"curl\s+.*(--upload-file|-T|-d\s+@)\s*[~$]", "Data exfiltration: curl upload of local files"),
    (r"curl\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys|known_hosts)", "Credential theft: accessing sensitive files"),
    (r"wget\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys)", "Credential theft: wget sensitive files"),
    (r"cat\s+(~/\.ssh|~/.aws|/etc/passwd|/etc/shadow)", "Credential theft: reading system credentials"),
    (r"eval\s*\(\s*base64\s*-d", "Obfuscated execution: eval base64 decode"),
    (r'\$\(.*base64.*-d.*\)', "Obfuscated execution: command substitution with base64"),
    (r"curl\s+http[s]?://[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", "Raw IP address curl — suspicious"),

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scan.py (reported line 339)May include surrounding context.

python
(r"curl\s+.*(--upload-file|-T|-d\s+@)\s*[~$]", "Data exfiltration: curl upload of local files"),
    (r"curl\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys|known_hosts)", "Credential theft: accessing sensitive files"),
    (r"wget\s+.*(\.ssh|id_rsa|\.aws|\.env|authorized_keys)", "Credential theft: wget sensitive files"),
    (r"cat\s+(~/\.ssh|~/.aws|/etc/passwd|/etc/shadow)", "Credential theft: reading system credentials"),
    (r"eval\s*\(\s*base64\s*-d", "Obfuscated execution: eval base64 decode"),
    (r'\$\(.*base64.*-d.*\)', "Obfuscated execution: command substitution with base64"),
    (r"curl\s+http[s]?://[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", "Raw IP address curl — suspicious"),

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scan.py (reported line 340)May include surrounding context.

python
(r"~/\.aws|/\.aws/", "AWS credentials access"),
        (r"~/\.config/.*token|~/\.config/.*secret", "Token/secret config access"),
        (r"/etc/passwd|/etc/shadow", "System password file access"),
        (r"~/Library/Keychains", "macOS Keychain access"),
        (r"wallet\.(dat|json)|keystore", "Crypto wallet access"),
    ]

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises no explicit tool scope or permissions while its documented and implied operation requires reading files and invoking a shell/Python command (python3 .../scan.py <path>). That mismatch can cause users or orchestration systems to grant broader access implicitly than the manifest declares, reducing transparency and weakening least-privilege controls.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The scanner advertises script scanning broadly, but endpoint and permission checks only inspect scripts/ and only some extensions, while other logic scans root-level files and additional languages. These coverage gaps can let a malicious skill hide network calls or sensitive-file access in unscanned locations or file types, undermining the scanner's verdict.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill claims to detect permission mismatches, but the implementation only flags sensitive-path patterns and does not compare observed behavior against a declared permission model. This can create a false sense of safety, allowing risky skills with undeclared capabilities to pass review or receive weaker findings than warranted.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The inline SECURITY MANIFEST at L002-L006 presents a narrow operational summary focused on read-only scanning with no writes or external calls. However, the script also performs process-control side effects via sys.exit and outputs detailed reports, making the documentation materially incomplete for how the tool actually behaves, though not maliciously so.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.