Back to skill

Security audit

Raon OS

Security checks for vulnerabilities and agentic risk

Overview

This is a real startup-assistant skill, but it has serious web-server and widget security issues that should be reviewed before installation.

Do not expose the bundled server to a network or embed the widget in a trusted site until the path traversal, feedback authentication, XSS, request limits, and key-storage issues are fixed. If testing locally, use minimal API keys in a dedicated config, avoid confidential business plans, and prefer localhost-only binding.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (7)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/raon.sh:343
Finding

Remote installation script executed through a shell pipeline

Content
View full analysis
/dev/null; then echo -e "${YELLOW}Ollama 미설치 — 자동 설치 시도...${NC}" if command -v brew &>/dev/null; then brew install ollama && echo -e "${GREEN}✅ Ollama 설치 완료${NC}" else echo -e "${YELLOW}Homebrew 미설치. 아래 명령어로 수동 설치하세요:${NC}" echo " curl -fsSL https://ollama.ai/install.sh | sh" exit 1 fi fi ``` ### Technical Analysis The `install-model` workflow instructs users to pipe a mutable network response directly into a shell. Although the command is displayed rather than automatically executed, it is part of the documented installation path presented by the Skill. TLS protects the connection in transit but does not make the downloaded script immutable. The effective code can change after this package has been audited. Compromise of the remote origin, CDN, DNS path, or publication account could consequently turn this installation step into arbitrary code execution. The downloaded content is not pinned to a version and is not verified using a checksum or digital signature. ### Attack Path 1. A user runs the `install-model` command on a system without Ollama or Homebrew. 2. The Skill displays `curl -fsSL https://ollama.ai/install.sh | sh` as the installation procedure. 3. The user copies and executes the command. 4. The current remote response is passed directly to the local shell. 5. If the remote source or delivery path has been compromised, attacker-controlled commands run with the invoking user's privileges. ### Impact Assessment A malicious remote script could: - Read or modify all files accessible to the invoking user. - Read credentials stored under the user's home directory. - Install persistence mechanisms. - Download and execute additional payloads. - Modify shell profiles or local development tools. - Ex ...[truncated 219 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/raon.sh:58
Finding

Arbitrary Python command execution through a crafted PDF filename

Content
View full analysis
/dev/null; then pdftotext "$file" - elif command -v python3 &>/dev/null; then python3 -c " import sys try: import PyPDF2 reader = PyPDF2.PdfReader('$file') for page in reader.pages: print(page.extract_text() or '') except ImportError: try: import pdfplumber with pdfplumber.open('$file') as pdf: for page in pdf.pages: print(page.extract_text() or '') except ImportError: print('ERROR: pdftotext, PyPDF2, or pdfplumber required', file=sys.stderr) sys.exit(1) " ``` ### Technical Analysis The user-controlled file path is interpolated directly into a Python program passed to `python3 -c`. Shell quoting around the outer program does not protect the Python string literal. A filename containing a single quote and valid Python syntax can terminate the `PdfReader` or `pdfplumber.open` string and inject additional Python statements. The vulnerable path is reached when `pdftotext` is unavailable and Python is selected as the fallback parser. This is source-code injection rather than ordinary argument injection: attacker-controlled data becomes part of the Python program itself. ### Attack Path 1. An attacker provides or causes the user to save a PDF with a filename containing a quote and Python syntax. 2. The user invokes PDF processing with that filename. 3. The target system does not have `pdftotext`, so the Python fallback is selected. 4. The filename is inserted into the `python3 -c` source code. 5. The crafted filename closes the quoted path and introduces attacker-controlled Python statements. 6. Python executes those statements with the privileges of the user running Raon OS. ### Impact Assessm ...[truncated 475 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/server.py:699
Finding

Unauthenticated arbitrary file disclosure through widget path traversal

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
widget/raon-chat.js:119
Finding

DOM and persistent cross-site scripting in chat widgets

Content
View full analysis
').replace(/\*\*(.*?)\*\*/g,'$1'); addMsg((d.score ? '
📊 '+d.score+'점
' : '') + res, 'bot'); } else addMsg('⚠️ ' + (d.error||'오류'), 'bot'); } catch(e) { ld.remove(); addMsg('⚠️ 서버 연결 실패', 'bot'); } } ``` The full-page widget additionally persists and restores raw HTML: ```javascript msgs.push({ type: m.classList.contains('msg-user')?'user':'bot', html: m.querySelector('.msg-content')?.innerHTML || '' }); localStorage.setItem('raon_convs', JSON.stringify(conversations)); ``` ```javascript conv.msgs.forEach(m => addMsg(m.html, m.type)); ``` ### Technical Analysis `addMsg()` treats its argument as trusted markup and assigns it to `innerHTML`. The value can originate from: - Raw user chat input. - LLM-generated output. - API response fields. - Idea metadata. - Previously stored ...[truncated 1875 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/server.py:848
Finding

Missing authentication enforcement on the feedback endpoint

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/server.py:154
Finding

Bearer API keys stored in plaintext without enforced file permissions

Content
View full analysis
None with open(str(path), "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) def _load_api_keys(): # type: () -> Dict[str, Any] """Returns {key_string: key_obj}""" raw = _load_json(API_KEYS_FILE) if isinstance(raw, list): return {k["key"]: k for k in raw} return raw def _save_api_keys(keys_dict): # type: (Dict[str, Any]) -> None _save_json(API_KEYS_FILE, keys_dict) ``` Generated keys are inserted in recoverable form: ```python new_key = _generate_api_key() key_obj = { "key": new_key, "user_id": body.get("user_id", ""), "plan": body.get("plan", "free"), "created_at": datetime.now(timezone.utc).isoformat(), "active": True, } with _data_lock: keys = _load_api_keys() keys[new_key] = key_obj _save_api_keys(keys) ``` ### Technical Analysis The server stores live bearer keys in plaintext JSON. `_save_json()` relies on the process umask and does not enforce restrictive file or directory permissions. These are bearer credentials: possession is sufficient to authenticate. A local user or process that can read the file can reuse the keys. The complete secret is also duplicated as both the dictionary key and the `key` field. ### Attack Path 1. An administrator creates an API key through the local administration endpoint. 2. `_save_api_keys()` writes the complete bearer key to `scripts/data/api_keys.json`. 3. The operating system applies the current process umask. 4. If the resulting file or parent directory is readable by another local account or service, that principal reads the JSON file. 5. The stolen bearer key is submitted to protected `/v1/` endpoints. ### Impa ...[truncated 437 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/server.py:375
Finding

Unbounded HTTP and PDF processing permits resource exhaustion

Content
View full analysis
str: """Base64 PDF → text using pypdf (fallback: PyPDF2, pdfplumber).""" raw = base64.b64decode(b64data) with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as f: f.write(raw) tmp = f.name try: try: from pypdf import PdfReader reader = PdfReader(tmp) return "\n".join(p.extract_text() or "" for p in reader.pages).strip() except ImportError: pass try: from PyPDF2 import PdfReader as PdfReader2 reader = PdfReader2(tmp) return "\n".join(p.extract_text() or "" for p in reader.pages).strip() except ImportError: pass import pdfplumber with pdfplumber.open(tmp) as pdf: return "\n".join(p.extract_text() or "" for p in pdf.pages).strip() finally: os.unlink(tmp) ``` Request bodies are read in full: ```python content_length = int(self.headers.get("Content-Length", 0)) if content_length == 0: self._send_error(400, "empty_body") return try: body = json.loads(self.rfile.read(content_length)) except json.JSONDecodeError: self._send_error(400, "invalid_json") return text = body.get("text", "").strip() pdf_b64 = body.get("pdf_base64", "").strip() ``` ### Technical Analysis The server does not enforce a maximum `Content-Length`, Base64 input size, decoded PDF size, page count, extracted-text size, or parsing time. The request JSON, Base64 string, decoded bytes, temporary file, PDF parser structures, per-page strings, and joined output may all exist during one request. Adversarial PDFs can also require disproportionate CPU or memory during parsing. Altho ...[truncated 1354 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (110)

Tainted flow: 'OLLAMA_URL' from os.environ.get (line 69, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The code sends a network request to a URL derived from the OLLAMA_URL environment variable without validating the scheme, host, or destination. If an attacker can influence environment variables, this can turn a harmless health check into SSRF-like behavior or exfiltration to an attacker-controlled endpoint, especially because other code also posts prompts and embeddings to the same base URL.

Content

Scanner excerpt · scripts/raon_llm.py (reported line 152)May include surrounding context.

python
def _ollama_available() -> bool:
    """Ollama 서버 응답 여부 확인 (3초 타임아웃)."""
    try:
        urllib.request.urlopen(f"{OLLAMA_URL}/api/tags", timeout=3)  # nosec B310
        return True
    except Exception:
        return False

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill markets a large startup network and advanced matching features without evidence those features exist. In security terms, this is dangerous because it can induce trust and data disclosure under false pretenses, particularly for founders uploading sensitive business plans and funding materials.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The skill explicitly relies on reading API keys from ~/.openclaw/.env, which is credential access by design. In a skill that also has shell, file, and network capabilities, access to centralized local API secrets is sensitive because compromise or misuse could leak keys to remote providers or expose billing and data under the user’s accounts.

Content

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

md
required: false
    requires:
      bins: ["python3", "node"]
    notes: "At least one LLM API key (GEMINI, OPENROUTER, ANTHROPIC, or OPENAI) is recommended. Falls back to local Ollama if no keys are set. API keys are stored in ~/.openclaw/.env (user-managed, chmod 600 recommended). The skill includes a local HTTP server (port 8400) and crawlers for public government data collection."
---

# Raon OS — Startup Companion (v0.7.10)

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The install instructions direct users to place API keys in a shared local .env that the skill will consume. That creates a clear secret-access surface, and given the skill’s undocumented server/network features, the context makes unauthorized disclosure or overbroad use of those credentials more dangerous.

Content

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

md
openclaw skill install @yeomyeonggeori/raon-os

# 3. API 키 설정 (권장: OpenRouter)
echo "OPENROUTER_API_KEY=your-openrouter-key" >> ~/.openclaw/.env
chmod 600 ~/.openclaw/.env  # 보안: 소유자만 읽기/쓰기

# 4. 모델 override (선택) — 기본은 프로바이더별 최적 모델 자동 선택

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The documentation shows direct manipulation of ~/.openclaw/.env, confirming that the skill ecosystem expects local plaintext credential storage and retrieval. This is risky in combination with broad capabilities and unclear behavior because users may not realize the skill can access credentials unrelated to the immediate task.

Content

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

md
# 3. API 키 설정 (권장: OpenRouter)
echo "OPENROUTER_API_KEY=your-openrouter-key" >> ~/.openclaw/.env
chmod 600 ~/.openclaw/.env  # 보안: 소유자만 읽기/쓰기

# 4. 모델 override (선택) — 기본은 프로바이더별 최적 모델 자동 선택
echo "RAON_MODEL=anthropic/claude-opus-4-5" >> ~/.openclaw/.env

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The sequence of writing secrets to .env and then running a detection script strongly implies the script reads local credentials to probe providers. That is normal functionality, but it is still sensitive credential access and should be treated as high impact because leaked API keys can enable third-party account abuse and data exposure.

Content

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

md
chmod 600 ~/.openclaw/.env  # 보안: 소유자만 읽기/쓰기

# 4. 모델 override (선택) — 기본은 프로바이더별 최적 모델 자동 선택
echo "RAON_MODEL=anthropic/claude-opus-4-5" >> ~/.openclaw/.env

# 5. 연결 테스트
python3 scripts/raon_llm.py --detect

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The sample .env lists multiple high-value provider keys in one place, increasing the blast radius if the file is read by an overprivileged or compromised skill. In this startup-document context, compromise would affect both confidentiality of user prompts/documents and financial exposure through API abuse.

Content

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

모든 API 키는 ~/.openclaw/.env 에 저장 (환경변수 우선):

bash
# ~/.openclaw/.env 예시
OPENROUTER_API_KEY=<your-key>   # 1순위 (추천)
GEMINI_API_KEY=<your-key>          # 2순위 + 임베딩
ANTHROPIC_API_KEY=<your-key>       # 3순위

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Referencing and auto-loading a shared .env file is a form of local credential access because it reads secrets from disk into the process environment. In this skill, that access is broader than necessary and happens implicitly, increasing the chance of unintended credential use by later components.

Content

Scanner excerpt · scripts/raon.sh (reported line 21)May include surrounding context.

sh
COMMAND="${2:-}"
shift 2 2>/dev/null || true

# --- .env 자동 로드 (환경변수 미설정 키만 적용) ---
if [ -f "${HOME}/.openclaw/.env" ]; then
  while IFS='=' read -r _k _v; do
    # 주석·빈줄 건너뜀, 이미 설정된 변수는 덮어쓰지 않음

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The file existence check and subsequent read from ${HOME}/.openclaw/.env confirms and accesses a local secret store without prompting the user. This is dangerous because a startup-advisor skill should not silently enumerate and consume credentials from a shared location.

Content

Scanner excerpt · scripts/raon.sh (reported line 22)May include surrounding context.

sh
shift 2 2>/dev/null || true

# --- .env 자동 로드 (환경변수 미설정 키만 적용) ---
if [ -f "${HOME}/.openclaw/.env" ]; then
  while IFS='=' read -r _k _v; do
    # 주석·빈줄 건너뜀, 이미 설정된 변수는 덮어쓰지 않음
    [[ -z "${_k}" || "${_k}" == \#* ]] && continue

Static analysis

Detected: suspicious.dangerous_exec, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
bin/raon-os.js:10

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/conftest.py:5

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/server.py:560