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## 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
## 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## 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
## 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## 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
## 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
Content
- **One script.** `scan.py` uses Python 3 stdlib only — no pip installs, no dependencies.
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Instruction Override

High
Category
Prompt Injection
Content
# 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"),
Confidence
80% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

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
Content
�─────────────────────────
# 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
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
# 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"),
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.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
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"),
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.

Instruction Override

High
Category
Prompt Injection
Content
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"),
Confidence
90% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

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
Content
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+@)\
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Credential Access

High
Category
Privilege Escalation
Content
(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"),
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
(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"),
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
(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"),
Confidence
95% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
(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"),
Confidence
95% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
(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"),
    ]
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

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.

Description-Behavior Mismatch

Medium
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.

Description-Behavior Mismatch

Medium
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.

Intent-Code Divergence

Low
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.

Static analysis

No suspicious patterns detected.