Back to skill

Security audit

Openclaw Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real URL scanner, but flaws in its trust logic and setup flow can cause risky links to be reported as safe.

Install only if you treat results as advisory, not as proof a link is safe. Be especially cautious with Taiwan public-suffix domains and with scans performed while GitHub data is unavailable. Avoid running the optional bulk download unless the publisher validates shard filenames or pins and verifies the downloaded data.

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)

T09 · Insecure Skill Coding Practices

Error
Location
lib/check_url.py:27
Finding

Public suffix allowlisting bypasses all phishing detection

Content
View full analysis
bool: """Check if domain is in whitelist.""" root = get_root_domain(domain) for w in WHITELIST: if domain == w or domain.endswith("." + w) or root == w: return True return False ``` ```python # Whitelist check if is_whitelisted(domain): return { "url": url, "domain": domain, "risk_level": "low", "risk_level_zh": "安全", "matched_source": None, "reasons": [], "message": f"{domain} 未發現已知風險。", } ``` ### Technical Analysis The allowlist contains public registration suffixes such as `com.tw` and `org.tw`. The `domain.endswith("." + w)` condition consequently trusts every registrable domain beneath those suffixes. Allowlist evaluation occurs before blocklist and heuristic evaluation. Once a suffix match is found, the function immediately returns a low-risk result. This means that neither a blocklist entry nor obvious phishing characteristics can override the allowlist decision. This is a fail-open trust-boundary error: public namespace suffixes are treated as if they were individually con ...[truncated 1130 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
lib/check_url.py:123
Finding

Blocklist retrieval failures are reported as low-risk results

Content
View full analysis
= 2: return { "url": url, "domain": domain, "risk_level": "high", "risk_level_zh": "高風險", "matched_source": "啟發式偵測", "reasons": reasons, "message": f"{domain} 具有多項可疑特徵。", } elif len(reasons) == 1: return { "url": url, "domain": domain, "risk_level": "medium", "risk_level_zh": "中風險", "matched_source": "啟發式偵測", "reasons": reasons, "message": f"{domain} 有可疑特徵。", } # No match return { "url": url, "domain": domain, "risk_level": "low", "risk_level_zh": "未發現風險", "matched_source": None, "reasons": [], "message": f"{domain} 未發現已知風險。", } ``` ### Technical Analysis Network failures, malformed upstream JS ...[truncated 1754 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
setup.sh:61
Finding

Unvalidated upstream shard filenames permit path traversal during bulk download

Content
View full analysis
/dev/null; then break fi if [ "$attempt" -lt 3 ]; then echo " ⏳ Retry $attempt..." sleep 3 else echo " ⚠️ Failed to download $shard (skipped)" fi done done ``` ### Technical Analysis The `--download-all` workflow retrieves a mutable `index.json` from an external repository and trusts each supplied filename as both a URL path and a local destination path. The validation only checks whether some string values end in `.json`; dictionary-based `file` values do not even receive that check. Directory separators, absolute paths, and `..` path components are not rejected. Consequently, an index value such as `../../../target.json` is joined directly to `DATA_DIR`, allowing the resulting output path to escape the intended blocklist directory. The downloaded files are not authenticated through a pinned revision, signature, or checksum. Therefore, compromise of the upstream repository, account, branch, or delivery path could modify both filenames and contents after the skill itself has been reviewed. ### Attack Path 1. An attacke ...[truncated 1346 chars]
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill's documented behavior materially differs from what it appears to do: it fetches data from GitHub, makes strong claims about intelligence coverage that are not substantiated here, and may use hardcoded whitelisting to mark domains safe. In a security tool, misleading users about data sources, detection coverage, or what is transmitted can create false trust and unsafe decisions, especially if malicious links are incorrectly labeled safe.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill invokes shell commands, accesses local files, and performs outbound network requests without declaring explicit tool scope or permissions. This weakens sandboxing and user/operator visibility, making it easier for the skill to overreach or be granted broader capabilities than its stated purpose requires.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The invocation rule is broad enough to trigger proactive URL checking whenever messages contain URLs and merely suggest a desire for safety advice. Because checking a URL can cause network fetches for shard data and initiate security-sensitive analysis without an explicit user request, this can create privacy surprises, unnecessary external requests, and unintended processing of benign conversations.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill’s security verdicts depend on blocklist data fetched at runtime from a GitHub raw URL, while the description implies stable built-in threat-intelligence coverage. This creates a trust and integrity gap: classifications can change based on remote content availability or compromise, and users may rely on results without realizing the data source is mutable and network-dependent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code returns user-facing strings in Traditional Chinese such as "黑名單" and multiple risk explanations, and the pattern continues throughout the result objects. Because the skill does not offer locale selection or indicate that it is intentionally region-specific, it appears to enforce a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The stated purpose is to assess whether a URL is safe or fraudulent, which obviously justifies parsing URLs and consulting threat data. Persisting cache files under '~/.cache/phishguard' is an extra filesystem-write capability not disclosed in the manifest and not necessary to understand from the user's perspective for a one-shot link checker.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.