Back to skill

Security audit

OpenClaw Glasses (多源搜索+意图感知+权重自适)

Security checks for vulnerabilities and agentic risk

Overview

This search skill has useful, disclosed retrieval features, but it needs review because it can silently reuse GitHub credentials, recursively fetch arbitrary URLs, and send fetched content to configured LLM providers.

Install only if you are comfortable with a search skill that can make broad outbound web/API requests, use configured search/LLM provider keys, and currently may reuse your GitHub credentials automatically. Review or patch the GitHub token discovery, add private-network URL blocking and redirect validation, and require explicit opt-in before recursive crawling or sending fetched page/comment content to an external LLM.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_thread.py:790
Finding

Arbitrary URL Fetching Enables SSRF and External Disclosure of Retrieved Internal Content

Content
View full analysis
dict: """Fetch a generic web page and extract references with anchor context.""" result = { "url": url, "type": "web_page", "title": "", "body": "", "state": None, "labels": [], "comments": [], "refs": [], "links": [], "metadata": {}, } try: req = Request(url, method="GET", headers={ "User-Agent": "Mozilla/5.0 (compatible; fetch-thread/1.0)" }) with urlopen(req, timeout=20) as resp: html = resp.read().decode("utf-8", errors="replace") ``` The recursive tracker passes seed URLs and discovered URLs directly to this fetcher: ```python # Fetch content sys.stderr.write(f"[chain_tracker] depth={depth} fetching: {url}\n") try: data = fetch_thread.fetch_thread_url(url) except Exception as e: sys.stderr.write(f"[chain_tracker] fetch failed: {e}\n") continue # Record node node = { "url": url, "depth": depth, "type": data.get("type", "unknown"), "title": data.get("title", ""), "body": (data.get("body", "") or "")[:2000], "comments": data.get("comments", [])[:10], "score": score, "reason": reason, } nodes.append(node) # Update knowledge state knowledge_state = _update_knowledge(knowledge_state, node, creds) ``` Fetched content is then included in a prompt sent to the configured external LLM endpoint: ```python def _update_knowledge(knowledge_state: str, node: dict, creds: dict) -> str: """Ask LLM to update knowledge_state after reading a new node.""" title = node.get("title", "") body = (node.get("bo ...[truncated 4152 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/fetch_thread.py:70
Finding

Silent Discovery and Reuse of GitHub Credentials Violates Least Privilege

Content
View full analysis
str | None: """Find GitHub token from env or git-credentials.""" if tok := os.environ.get("GITHUB_TOKEN"): return tok if tok := os.environ.get("GH_TOKEN"): return tok cred_path = os.path.expanduser("~/.git-credentials") if os.path.isfile(cred_path): try: with open(cred_path) as f: for line in f: line = line.strip() if "github.com" in line: # Format: https://user:token@github.com match = re.search(r'://[^:]+:([^@]+)@github\.com', line) if match: return match.group(1) except Exception: pass return None def _gh_headers(token: str | None) -> dict: headers = {"Accept": "application/vnd.github+json"} if token: headers["Authorization"] = f"Bearer {token}" return headers ``` The recovered token is automatically used for GitHub API requests: ```python def fetch_github_issue(owner: str, repo: str, number: int, token: str | None, max_comments: int = 100) -> dict: """Fetch a GitHub issue with all comments via REST API.""" base = f"https://api.github.com/repos/{owner}/{repo}" headers = _gh_headers(token) ``` ### Technical Analysis The Skill silently inspects the user's global plaintext Git credential store at `~/.git-credentials`, extracts a GitHub password or token embedded in a credential URL, and uses that credential as a bearer token. This access is not ...[truncated 2304 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (44)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Undeclared post-search URL fetching, content/reference extraction, and direct GitHub issue/PR access extend the skill beyond simple search into active content retrieval and repository-linked data access. When these behaviors are not clearly disclosed, they can expose users to prompt injection from fetched pages, expand network access unexpectedly, and potentially touch private or authenticated resources.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Undeclared post-search URL fetching, content/reference extraction, and direct GitHub issue/PR access extend the skill beyond simple search into active content retrieval and repository-linked data access. When these behaviors are not clearly disclosed, they can expose users to prompt injection from fetched pages, expand network access unexpectedly, and potentially touch private or authenticated resources.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Undeclared post-search URL fetching, content/reference extraction, and direct GitHub issue/PR access extend the skill beyond simple search into active content retrieval and repository-linked data access. When these behaviors are not clearly disclosed, they can expose users to prompt injection from fetched pages, expand network access unexpectedly, and potentially touch private or authenticated resources.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Undeclared post-search URL fetching, content/reference extraction, and direct GitHub issue/PR access extend the skill beyond simple search into active content retrieval and repository-linked data access. When these behaviors are not clearly disclosed, they can expose users to prompt injection from fetched pages, expand network access unexpectedly, and potentially touch private or authenticated resources.

Content

No source excerpt is available for this finding.

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
80% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · references/research-light-regression-samples.md (reported line 39)May include surrounding context.

md
| N6 | news | deep | AI news this week 2026 | ordinary news multi-query, no reasoning signal |
| N7 | status | deep | Deno 2.0 latest status | status without analysis signal |
| N8 | status | deep | PostgreSQL 18 release date | status factual, no reasoning |
| N9 | exploratory | deep | RISC-V ecosystem overview | exploratory without judgment/causal |
| N10 | exploratory | deep | Kubernetes 生态 | broad topic word only |
| N11 | comparison | deep | Bun ecosystem maturity | comparison intent but no compare/judgment signal |
| N12 | status | deep | Deno 2.0 latest 2026 | status multi-query without reasoning signal |

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

Reading ~/.git-credentials is direct access to a local secret store and is especially sensitive because it extracts reusable GitHub tokens from persistent credentials. In this skill context, that behavior is more dangerous because the manifest describes a search-layer capability, not local credential harvesting, so the access is unnecessary and unexpected.

Content

Scanner excerpt · scripts/fetch_thread.py (reported line 76)May include surrounding context.

python
return tok
    if tok := os.environ.get("GH_TOKEN"):
        return tok
    cred_path = os.path.expanduser("~/.git-credentials")
    if os.path.isfile(cred_path):
        try:
            with open(cred_path) as f:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares no explicit tool scope even though the implementation reportedly uses environment access, file reads/writes, and network operations. Missing permission boundaries can let an agent invoke capabilities beyond what a user would reasonably infer from a 'search-layer' skill, increasing the risk of unintended secret access, local file interaction, or uncontrolled outbound requests.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation guidance is broad enough to match many ordinary requests, which increases the chance the skill will be invoked unnecessarily or by default. In a skill with network, file, and possible credential-touching behavior, overbroad triggering expands exposure and can cause the agent to route benign tasks through a more privileged path than needed.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
77% confidence
Finding

Enforcing bilingual or Chinese-specific handling without clear user opt-in can create privacy, relevance, and expectation issues, such as routing queries to different sources or applying language-specific weighting the user did not request. While not as severe as credential or scope problems, it still represents undisclosed behavior modification in a retrieval skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The guide hard-codes Chinese-query handling and English query expansion without indicating user consent or preference checks. This can expose user queries to additional third-party processing, alter the user’s intended linguistic scope, and create privacy or policy issues when users expect searches to remain in one language.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The language adaptation rule explicitly requires Chinese technical queries to also be searched in English, which broadens data disclosure and can return sources outside the user’s intended language or jurisdiction. In a search-layer skill, this is more significant because it systematically affects many queries and may undermine user expectations around privacy, localization, and result fidelity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The knowledge-state updater sends fetched page body text and comments to an LLM through relevance_gate._call_llm without any visible consent, minimization, or classification of the transmitted data. This can expose third-party content, sensitive page material, or user-linked research context to an external model provider, creating privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script performs recursive crawling from seed URLs, follows extracted links, and uses LLM-based scoring to continue traversal. For a search-layer skill, this expands behavior from bounded retrieval into autonomous off-search exploration, which can reach unintended domains, increase data collection, and trigger additional external requests beyond what a user likely expects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The tracker fetches remote content recursively, extracts candidate links, and sends candidate metadata plus evolving knowledge state to an external scoring function, causing repeated network access and onward transmission of derived content without a clear user warning. This compounds privacy, compliance, and operational risk because each hop may pull in more third-party data and broaden exposure unexpectedly.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This file is a URL fetcher that retrieves and parses discussion threads from GitHub, V2EX, Hacker News, Reddit, or generic web pages, then extracts references. It does not implement the manifest's headline capabilities such as intent-aware ranking, adaptive weighting, Chinese-query optimization, broader search orchestration, or finance-aware realtime prioritization, indicating a semantic mismatch between claimed skill behavior and actual code in this component.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script automatically harvests GitHub credentials from environment variables and ~/.git-credentials, then uses them in outbound API requests without explicit user consent. In an agent skill whose stated purpose is search/retrieval, this creates an unnecessary secret-access path and can cause privileged identity use, token exposure to remote services, or access to private repository metadata the user did not intend to disclose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The credential lookup is silent and non-interactive, so users may not realize their GitHub identity and token are being used for requests. In agent environments, this violates least surprise and can lead to unauthorized use of secrets, fetching private data under the user's account, or sending authenticated requests to remote endpoints without approval.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_thread.py (reported line 245)May include surrounding context.

python
def fetch_github_issue(owner: str, repo: str, number: int,
                       token: str | None, max_comments: int = 100) -> dict:
    """Fetch a GitHub issue with all comments via REST API."""
    base = f"https://api.github.com/repos/{owner}/{repo}"
    headers = _gh_headers(token)
    result = {
        "url": f"https://github.com/{owner}/{repo}/issues/{number}",

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_thread.py (reported line 378)May include surrounding context.

python
def fetch_github_issue(owner: str, repo: str, number: int,
                       token: str | None, max_comments: int = 100) -> dict:
    """Fetch a GitHub issue with all comments via REST API."""
    base = f"https://api.github.com/repos/{owner}/{repo}"
    headers = _gh_headers(token)
    result = {
        "url": f"https://github.com/{owner}/{repo}/issues/{number}",

Ssd 1

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Untrusted anchor text and page context are concatenated directly into a single prompt with the scoring instructions, so attacker-controlled page text can inject semantic instructions such as telling the model to up-rank or down-rank specific links. In this skill, relevance scoring directly influences which sources are followed next, making prompt injection a practical way to bias retrieval, suppress good sources, or steer the agent toward attacker-controlled content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code sends the user's query, knowledge_state, and candidate link metadata to an external LLM provider for scoring, but there is no consent gate, redaction, or policy check in this component. In a research/search skill, those fields can contain sensitive user intent, proprietary notes, or internal URLs, so this creates a real data-exposure risk to a third party.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/search.py (reported line 436)May include surrounding context.

python
symbol = _extract_binance_symbol(query)
        if not symbol:
            return []
        r = requests.get("https://api.binance.com/api/v3/ticker/24hr", params={"symbol": symbol}, timeout=15)
        r.raise_for_status()
        data = r.json()
        trade_symbol = symbol.replace("USDT", "_USDT")

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/search.py (reported line 545)May include surrounding context.

python
keys["gemini_model"] = gemini.get("model", "gemini-2.5-flash")
            if kimi := cred.get("kimi"):
                if isinstance(kimi, dict):
                    keys["kimi_url"] = kimi.get("apiUrl", kimi.get("baseUrl", "https://api.moonshot.ai/v1"))
                    keys["kimi_key"] = kimi.get("apiKey", "")
                    keys["kimi_model"] = kimi.get("model", "kimi-k2-0711-preview")
        except (json.JSONDecodeError, FileNotFoundError):

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/search.py (reported line 561)May include surrounding context.

python
keys["gemini_model"] = gemini.get("model", "gemini-2.5-flash")
            if kimi := cred.get("kimi"):
                if isinstance(kimi, dict):
                    keys["kimi_url"] = kimi.get("apiUrl", kimi.get("baseUrl", "https://api.moonshot.ai/v1"))
                    keys["kimi_key"] = kimi.get("apiKey", "")
                    keys["kimi_model"] = kimi.get("model", "kimi-k2-0711-preview")
        except (json.JSONDecodeError, FileNotFoundError):

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/search.py (reported line 1342)May include surrounding context.

python
keys["gemini_model"] = gemini.get("model", "gemini-2.5-flash")
            if kimi := cred.get("kimi"):
                if isinstance(kimi, dict):
                    keys["kimi_url"] = kimi.get("apiUrl", kimi.get("baseUrl", "https://api.moonshot.ai/v1"))
                    keys["kimi_key"] = kimi.get("apiKey", "")
                    keys["kimi_model"] = kimi.get("model", "kimi-k2-0711-preview")
        except (json.JSONDecodeError, FileNotFoundError):

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/search.py:1435