Back to skill

Security audit

Openclaw Web Browser

Security checks for vulnerabilities and agentic risk

Overview

This skill is a plausible web scraping and monitoring toolkit, but it needs review because its URL fetching, scheduled monitoring, and local file storage are under-scoped.

Install only if you are comfortable granting it network access and local JSON file writes. Use it only for public URLs you explicitly choose, avoid cron until you have reviewed stored monitors, do not use --insecure except for isolated diagnostics, and run it from a constrained directory or sandbox until URL and path validation are tightened.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetcher.py:247
Finding

Unrestricted URL Fetching Enables Server-Side Request Forgery in the Web Fetcher

Content
View full analysis
Optional[Dict[str, Any]]: try: if not check_robots_txt(url): return { "url": url, "error": "robots.txt에 의해 차단됨 (Blocked by robots.txt)", "fetched_at": datetime.now(timezone.utc).isoformat() } rate_limit(url) response = requests.get( url, headers={"User-Agent": USER_AGENT}, timeout=REQUEST_TIMEOUT, allow_redirects=True ) response.raise_for_status() ``` The URL is taken directly from a command-line argument or batch file and passed to `requests.get()` without restricting the destination scheme, hostname, resolved IP address, or port. The `check_robots_txt()` function is not a security control; it also contacts a URL derived from the untrusted destination and permits access when `robots.txt` cannot be read. Automatic redirects are explicitly enabled, but each redirect target is not revalidated. Consequently, an initially public URL may redirect the request to a loopback, private, link-local, or otherwise privileged network destination. Fetched page content is parsed and returned through standard output or a caller-selected JSON file. This makes the flaw capable of disclosing responses, rather than being limited to blind SSRF. ### Attack Path 1. An attacker supplies a URL through the `fetch` command, a batch URL file, or content that causes an agent to invoke the fetcher with an attacker-selected URL. 2. The URL points directly to an internal service, such as a loopback administration endpoint, or to an attacker-controlled public endpoint that redirects to an internal address. 3. `check_robots_txt()` fails open if the robots fil ...[truncated 881 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/monitor.py:91
Finding

Stored Monitor URLs Enable Repeatable Server-Side Request Forgery

Content
View full analysis
Optional[str]: try: headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() return response.text except requests.RequestException as e: print(f"Error fetching {url}: {e}", file=sys.stderr) return None ``` ```python # URL 검증 try: urlparse(url) except Exception: print("Error: Invalid URL", file=sys.stderr) return False monitors[name] = { 'url': url, 'name': name, 'selectors': selectors, 'check_interval': check_interval, 'created_at': datetime.now().isoformat(), 'last_checked': None } ``` Calling `urlparse()` does not validate that a URL has an allowed scheme or safe destination. It generally parses malformed or dangerous values without raising an exception. The monitor therefore stores arbitrary URLs and later sends requests to them. Because the target is retained in `monitor-data/monitors.json`, subsequent `check`, `check-all`, or manually configured cron executions repeat the request. This turns the issue into stored SSRF. The documented cron configuration does not install persistence automatically and is legitimate for monitoring, but it can amplify an unsafe stored target after a user enables scheduling. ### Attack Path 1. An attacker convinces the user or agent to register a monitor whose URL targets an internal address or an attacker-controlled redirector. 2. `urlparse(url)` accepts the URL because no scheme, host, port, or resolved-address policy is enforced. 3. The URL is saved in `monitors.json`. 4. A manual `check`, `check-all`, or scheduled cron invocation calls `_fetc ...[truncated 830 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/monitor.py:144
Finding

Unsanitized Monitor Names Permit Directory Traversal and Out-of-Scope File Creation

Content
View full analysis
Optional[Dict[str, Any]]: monitor_dir = self.snapshots_dir / name if not monitor_dir.exists(): return None snapshot_files = sorted(monitor_dir.glob('*.json'), reverse=True) if not snapshot_files: return None try: with open(snapshot_files[0], 'r', encoding='utf-8') as f: return json.load(f) ``` ```python def _save_snapshot(self, name: str, data: Dict[str, Any]) -> None: monitor_dir = self.snapshots_dir / name monitor_dir.mkdir(parents=True, exist_ok=True) date_str = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") snapshot_file = monitor_dir / f"{date_str}.json" try: with open(snapshot_file, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) ``` ```python def _save_diff(self, name: str, diff_data: Dict[str, Any]) -> None: monitor_dir = self.diffs_dir / name monitor_dir.mkdir(parents=True, exist_ok=True) date_str = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") diff_file = monitor_dir / f"{date_str}_diff.json" try: with open(diff_file, 'w', encoding='utf-8') as f: json.dump(diff_data, f, ensure_ascii=False, indent=2) ``` The monitor name is accepted without validation and is used as a filesystem path component. A name containing `../` can escape the intended snapshots or diffs directory. With `pathlib`, an absolute `name` can also replace the preceding base path entirely. The attacker does not directly control the generated timestamp filename, so this is not a fully arbitrary filename overwrite. However, the attacker can select an arbitrary writable directory, cause JSON files to be created there, and make the snapshot loader inspect ...[truncated 1451 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:361
Finding

Documentation Recommends Disabling TLS Certificate Verification

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
README.md:13
Finding

Runtime Dependencies Are Installed Without Version or Integrity Pinning

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (32)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding

설명과 코드의 핵심은 전반적으로 웹 수집/추출/JSON 구조화 및 프리셋 기반 수집이라는 점에서 상당히 일치합니다. 그러나 설명의 중요한 일부가 코드에서 구현되지 않았습니다. 이 코드는 requests + BeautifulSoup 기반으로만 동작하며 브라우저 자동화, JavaScript 실행, 렌더링 대기 등 동적 페이지 처리 기능이 없습니다. 또한 변경사항 비교, 이전 수집본 저장/대조, 주기적 실행 스케줄러 같은 모니터링·정기 수집 기능도 코드에 없습니다. 반대로 코드에는 Google 검색 결과를 직접 수집하는 기능이 있는데, 설명에는 명시되어 있지 않습니다. 따라서 부분적 일치는 있으나, 선언된 주요 기능 일부가 과장되거나 누락되어 있어 설명-행동 불일치로 보는 것이 타당합니다.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

설명은 종합 웹 브라우징/스크래핑/모니터링 스킬을 주장하지만, 제공된 코드는 외부 웹사이트에 접속하지 않고 이미 주어진 HTML만 파싱하여 텍스트 또는 메타데이터로 변환한다. 즉, 핵심 목적이 '웹 수집 플랫폼'이 아니라 'HTML→텍스트/메타데이터 변환기'에 가깝다. 설명에 포함된 동적 페이지 지원, 정기 수집, 변경 감시, 항공기관 프리셋 등은 코드에서 확인되지 않는다. 따라서 declared purpose와 actual behavior 사이에 중대한 불일치가 있다.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

설명에는 정적/동적 웹페이지 브라우징, 정보 수집, 데이터 추출, JSON 구조화, 변경 모니터링, 정기 수집, 항공기관 특화 프리셋까지 포함된 종합 스킬이라고 되어 있다. 그러나 실제 코드 조각은 requests로 HTML을 단순 다운로드하고 BeautifulSoup CSS selector로 텍스트를 추출하는 정적 페이지 중심의 모니터링 도구다. Selenium/Playwright 같은 동적 렌더링 지원이 없고, 사용자가 수동으로 CLI를 실행해야 하므로 정기 수집 스케줄링 자체를 제공하지 않는다. 또한 항공기관용 프리셋이나 범용 브라우징/탐색 기능은 보이지 않는다. 변경 감지, 스냅샷 저장, JSON 구조화는 설명과 부합하지만, 전체 설명의 범위와 핵심 기능 주장에 비해 실제 구현은 더 좁고 일부 중요한 주장들이 누락되어 있어 불일치로 판단된다.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

선언된 설명은 범용 웹 브라우징 및 웹 데이터 수집 스킬을 묘사하지만, 실제 코드는 브라우저 자동화나 HTTP 요청, HTML 파싱, 크롤링, DOM 상호작용, 모니터링 루프, 스케줄 실행을 전혀 구현하지 않는다. URL 입력은 인터페이스에 존재하지만 명시적으로 '현재 미지원'으로 처리된다. 대신 실제 기능은 항공 도메인 문서 지식 기반을 로드해 키워드 추출, 문서 매칭/추천, 발행처별 비교, 개정 이력 조회를 수행하는 것이다. 따라서 선언된 목적과 실제 동작의 1차 목적이 materially different 하며 명백한 설명-행동 불일치다.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

The skill explicitly instructs use of curl piped into a local Python script for processing remote content, normalizing direct shell-based retrieval of untrusted data. While the shown pipeline does not execute remote code, encouraging shell/network/script chaining in skill instructions raises command-injection and unsafe-processing risk, especially if future examples add variable interpolation, relaxed TLS (--insecure is later suggested), or users adapt the pattern unsafely.

Content

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

md
---

## Layer 1: web_fetch / curl 사용법

가장 기본적이고 빠른 수집 방법.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · README.md (reported line 53)May include surrounding context.

md
HTML to Text Converter — stdin으로 받은 HTML을 읽기 좋은 텍스트로 변환

사용법:
    curl -sL "https://example.com" | python3 html_to_text.py
    cat page.html | python3 html_to_text.py --format markdown
    python3 html_to_text.py --file page.html --format plain
"""

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/html_to_text.py (reported line 6)May include surrounding context.

python
HTML to Text Converter — stdin으로 받은 HTML을 읽기 좋은 텍스트로 변환

사용법:
    curl -sL "https://example.com" | python3 html_to_text.py
    cat page.html | python3 html_to_text.py --format markdown
    python3 html_to_text.py --file page.html --format plain
"""

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The natural-language description uses Korean exclusively and does not indicate that the skill supports other languages or that Korean is a required regional/compliance constraint. The policy requires flagging language or locale constraints when a specific language is effectively forced without user opt-in.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 74)May include surrounding context.

정기 실행 (cron)

bash
# crontab -e
0 8 * * * cd ~/skills/web-browser-toolkit && python3 scripts/monitor.py check-all
0 9 * * 1 cd ~/skills/web-browser-toolkit && python3 scripts/monitor.py weekly-report

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documents use of shell, network access, and local file read/write capabilities (python3, curl, browser commands, monitor data storage) but does not declare any explicit tool scope or permissions boundary. In an agent environment, missing scope declarations increases the chance the skill is invoked with broader privileges than necessary, enabling unintended filesystem writes, network access, or command execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest description is written entirely in Korean, and the rest of the skill instructions are likewise Korean-only. This creates a language/locale constraint without any opt-in or documented region-specific justification, which matches the policy-violation criterion for forced language selection.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

The cron examples encourage persistent scheduled execution and storage of monitoring state, which can outlive the user’s immediate intent and continue making network requests or writing files unattended. In an agent/tooling context, persistence increases the risk of unauthorized long-running activity, stale tasks operating under outdated assumptions, or silent resource abuse if users copy these instructions directly.

Content

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

cron 연동 (정기 실행)

bash
# crontab -e
# 매일 오전 8시: 모든 모니터 체크
0 8 * * * cd ~/web-monitor && python3 scripts/monitor.py check-all

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

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

md
1. 브라우징 수집 완료 → 수집 JSON 생성 → `doc-recommender`가 tags 분석 → 관련 공식 문서 자동 추천
2. 사용자 직접 질문 → 키워드 추출 → 지식 베이스 매칭 → 추천 결과 제공

**상세 정보**: `sub-skills/doc-recommender/SKILL.md` 참고

---

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This JSON manifest contains a natural-language description only in Korean ('항공 기관별 웹 수집 프리셋...') with no indication that the skill is intentionally Korean-only or region-scoped. In a general-purpose skill, that can create an implicit language constraint without user opt-in and also leaves activation/usage context underspecified for non-Korean users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The only human-readable description in the file is written in Korean, and the file does not indicate that Korean is optional or required for a justified regional use case. This can violate language/locale policy when a skill implicitly forces a specific language instead of offering choice or documenting the constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code file makes outbound HTTP requests to Google using the user-provided search query, which transmits user data to a third party. While the function name indicates search behavior, there is no confirmation prompt, visible disclosure at execution time, or comment/docstring warning about external transmission or privacy implications.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language strings in Korean in the module docstring, help text, and error messages, but provides no user opt-in or explanation that the tool is intended only for Korean-speaking users. Under the policy, forcing a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code saves the current snapshot before loading the 'previous' snapshot, so _get_latest_snapshot(name) reads back the snapshot just written instead of the actual prior state. This breaks change detection integrity: modifications can be missed or misreported, undermining monitoring and any downstream alerting or reporting that depends on accurate diffs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The remove_monitor function deletes an entry from the persisted monitors configuration and immediately writes the updated data to monitors.json. Although it prints a success message afterward, there is no prior confirmation prompt or explicit warning that this action permanently changes saved monitoring configuration.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill description mandates using this module for broadly defined requests across aviation, legal, technical standards, government policy, and effectively any domain involving 'official documents.' That kind of over-broad routing can override user intent and cause inappropriate delegation to a web-searching/recommendation skill, increasing the chance of irrelevant retrieval, policy bypass through tool selection, or unsafe handling of sensitive/legal queries without proper scoping.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The description is written to operate in Korean and provides Korean-trigger examples without indicating any user language negotiation or fallback behavior. This can cause incorrect or inaccessible responses for users in other languages, and in a document-recommendation context may lead to misunderstandings of regulations, standards, or compliance materials due to forced localization assumptions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description contains broad trigger phrases such as '관련 규정 찾아줘', '공식 문서 추천', and '어떤 표준이 적용돼?' plus a mandatory rule stating this skill must always be used for such requests. That can cause over-routing of many generic research or recommendation prompts into this skill, increasing the chance of inappropriate tool invocation, unnecessary web access, and incorrect delegation beyond the user's actual intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file describes a monitoring feature that repeatedly checks URLs and generates reports, but it does not include any user-facing warning that the skill will perform recurring network requests and may collect/store fetched content metadata. For markdown files, SQP-2 applies when the description omits warnings about behaviors that could affect privacy or system integrity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The README instructs users to install cron jobs that will run monitoring commands automatically, but it does not warn that this creates unattended recurring execution with network access and possible local report/output generation. For markdown files, such automation should be disclosed when it could affect user data, privacy, or system behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file contains user-facing instructional content exclusively in Korean. Under the policy rule for natural-language violations, forcing a specific language without user opt-in can be a locale-policy issue when no justification or alternative is provided.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.