Back to skill

Security audit

API Logger

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real API logging tool, but it installs an always-on proxy that can retain and forward full AI conversations with weak safeguards.

Review carefully before installing. Use only in a controlled environment, change the upstream to HTTPS before routing traffic, avoid sending secrets or regulated data through it, and treat the log directory as sensitive. Prefer on-demand operation over the default LaunchAgent, and do not use Feishu export unless the external exporter and destination are trusted.

Vulnerability Patterns
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (5)

T06 · System Persistence

Error
Location
install.sh:45
Finding
Persistent LaunchAgent Installed and Kept Alive Without Separate Opt-In<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:45-89` **Vulnerability Type**: Persistent background service registration **Risk Level**: High ### Vulnerable Code ```bash # 5. Write LaunchAgent plist echo "Writing LaunchAgent plist: $PLIST_PATH" mkdir -p "$HOME/Library/LaunchAgents" cat > "$PLIST_PATH" << EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.lobster.api-proxy</string> <key>ProgramArguments</key> <array> <string>/usr/bin/python3</string> <string>${INSTALL_DIR}/proxy.py</string> <string>--port</string> <string>${PROXY_PORT}</string> <string>--upstream</string> <string>${UPSTREAM}</string> <string>--log-dir</string> <string>${LOG_DIR}</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>${LOG_DIR}/proxy.stdout.log</string> <key>StandardErrorPath</key> <string>${LOG_DIR}/proxy.stderr.log</string> <key>WorkingDirectory</key> <string>${INSTALL_DIR}</string> </dict> </plist> EOF # 6. Load LaunchAgent launchctl unload "$PLIST_PATH" 2>/dev/null || true launchctl load "$PLIST_PATH" ``` ### Technical Analysis The installer creates a macOS LaunchAgent with both `RunAtLoad` and `KeepAlive` enabled and immediately loads it. Consequently, the API interception proxy starts automatically in future login sessions and is restarted whenever it exits. Continuous operation can be useful for transparent API logging, and the behavior is disclosed in the documentation. However, an always-on, self-restarting service is not the minimum privilege or lifetime required for an on-demand log viewer or manually operated proxy. The installer provides no separate persistence confirmation, nonpersistent installation mode, ...[truncated 1180 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Run the proxy in the foreground or on demand by default. - Present persistence as a separate, explicit installation option requiring informed user consent. - Do not enable `KeepAlive` unless continuous restart behavior is strictly required. - Provide a documented uninstaller that unloads and deletes the LaunchAgent and optionally removes retained logs. - Restrict the installation directory and executable so they are writable only by the owning user. - Verify the ownership and permissions of the plist, installation directory, and proxy before loading the service. - Prefer modern `launchctl bootstrap` and `bootout` commands with explicit user-domain handling. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
install.sh:12
Finding
API Credentials and Conversation Data Forwarded to a Plaintext HTTP Upstream<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:12`, `proxy.py:205-231`, `proxy.py:344-345` **Vulnerability Type**: Cleartext transmission of sensitive information **Risk Level**: High ### Vulnerable Code ```bash UPSTREAM="http://model.mify.ai.srv/anthropic" ``` ```python # Forward headers (pass through as-is) forward_headers = {} for k, v in request.headers.items(): lower_k = k.lower() # Skip hop-by-hop headers if lower_k in ("host", "transfer-encoding"): continue forward_headers[k] = v streaming = is_streaming_request(body) async with self.session.request( method=request.method, url=upstream_url, headers=forward_headers, data=body, allow_redirects=False, ) as upstream_resp: ``` ```python parser.add_argument( "--upstream", type=str, default="http://model.mify.ai.srv/anthropic", help="Upstream API URL" ) ``` ### Technical Analysis The default upstream URL uses unencrypted HTTP. The proxy forwards incoming request headers—including authorization and API-key headers—and the complete request body to that endpoint without transport encryption. Header sanitization only affects the logged copy of the headers. It does not remove or encrypt credentials in the forwarded request, because forwarding valid authentication data is necessary for the upstream API call. When the destination uses HTTP, TLS does not protect those credentials or the associated prompts and responses. Although the hostname may resolve only in a private environment, private networks do not eliminate risks from compromised hosts, malicious gateways, DNS manipulation, packet capture, or incorrectly exposed network segments. ### Attack Path 1. The installer starts the proxy with the default `http://model.mify.ai.srv/anthropic` upstream. 2. The user configures an LLM client to send requests to the local proxy. 3. The client includes an API key or bearer token and potentially sensitive prompts. 4. The proxy forwards ...[truncated 706 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Change the default upstream to an HTTPS URL. - Reject non-HTTPS upstreams unless the destination is explicitly verified as loopback and the user supplies an override acknowledging the risk. - Keep TLS certificate and hostname verification enabled. - Remove the organization-specific upstream from the distributed package and require explicit configuration during installation. - Fail closed when an insecure or malformed upstream URL is supplied. - Clearly display the final upstream scheme and hostname before starting the persistent proxy. - Where supported, use short-lived, narrowly scoped credentials rather than long-lived API keys. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
proxy.py:59
Finding
Complete Prompts and Model Responses Stored in Plaintext Without Explicit Access Controls or Retention Limits<![CDATA[ ## Vulnerability Details **File Location**: `proxy.py:59-66`, `proxy.py:200-219`, `proxy.py:257-277` **Vulnerability Type**: Excessive plaintext storage of sensitive data **Risk Level**: High ### Vulnerable Code ```python def write_log(log_dir: str, entry: dict): """Append one JSON line to today's log file.""" path = get_log_path(log_dir) os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "a", encoding="utf-8") as f: f.write(json.dumps(entry, ensure_ascii=False) + "\n") ``` ```python # Parse request body for logging try: request_body_log = json.loads(body) if body else None except (json.JSONDecodeError, UnicodeDecodeError): request_body_log = body.decode("utf-8", errors="replace") if body else None log_entry = { "timestamp": start_time.isoformat(), "request_id": request_id, "method": request.method, "path": path, "query": query or None, "streaming": streaming, "request_headers": sanitize_headers(dict(request.headers)), "request_body": request_body_log, } ``` ```python raw_stream = b"".join(stream_chunks).decode("utf-8", errors="replace") log_entry["response_status"] = upstream_resp.status log_entry["response_headers"] = sanitize_headers(dict(upstream_resp.headers)) log_entry["response_body_raw_stream"] = raw_stream try: log_entry["response_body_parsed"] = json.loads( parse_sse_content(raw_stream) ) except (json.JSONDecodeError, Exception): log_entry["response_body_parsed"] = None log_entry["duration_ms"] = round((t1 - t0) * 1000, 2) write_log(self.log_dir, log_entry) ``` ### Technical Analysis The proxy intentionally records the complete request body and response. This can include system prompts, user conversations, generated text, tool arguments, tool results, source code, personal information, access tokens embedded in prompts, and other application secrets. Authentication headers are masked in the logged header copy, but there is no corresp ...[truncated 1527 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create the log directory with mode `0700` and each log file with mode `0600`, using secure open flags that prevent unsafe link following where applicable. - Make full-content logging opt-in. Default to metadata such as timestamp, status, model, token counts, and duration. - Add configurable redaction for message fields, query parameters, tool arguments, tool results, and custom headers. - Detect and mask common credentials, bearer tokens, private keys, cookies, and personally identifiable information in bodies. - Avoid storing both parsed and raw streaming responses unless explicitly requested for debugging. - Implement configurable retention, automatic expiration, maximum total size, and secure deletion workflows. - Warn users before enabling logging and document exactly which data is retained. - Consider authenticated encryption for logs containing sensitive content. ]]>

T08 · Insecure Dependencies

Warning
Location
install.sh:35
Finding
Unpinned Dependency Installed Into the Active Python Environment<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:35-41` **Vulnerability Type**: Unsafe dependency installation and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```bash # 4. Check aiohttp dependency echo "Checking Python dependencies..." if ! python3 -c "import aiohttp" 2>/dev/null; then echo "aiohttp not detected, installing..." pip3 install aiohttp --quiet echo "aiohttp installed" else echo "aiohttp is ready" fi ``` ### Technical Analysis If `aiohttp` is unavailable, the installer invokes `pip3 install aiohttp` without a pinned version, integrity hash, explicit package index, or isolated virtual environment. Package selection is therefore controlled by the active pip configuration and package index state at installation time. A compromised index, malicious mirror configuration, dependency compromise, or future incompatible release could cause unexpected code to be downloaded and executed. Python package installation can execute build-system code during installation. The script also assumes that `python3` and `pip3` refer to the same environment, which is not guaranteed. This can install into an unintended user or system environment and still leave the runtime dependency unresolved. ### Attack Path 1. The target environment does not already provide `aiohttp`. 2. The user runs `install.sh`. 3. The script invokes the first `pip3` found through `PATH`. 4. Pip consults its configured index and selects the latest acceptable package and transitive dependencies. 5. A compromised or malicious artifact executes installation-time code under the user's privileges. 6. The installed code is later imported by the persistent proxy, extending execution across sessions. ### Impact Assessment A malicious package or build dependency can execute code with the installing user's privileges. It may access the user's files and credentials, modify installed code, or exploit the LaunchAgent persistence established by the sa ...[truncated 156 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create a dedicated virtual environment for the proxy. - Pin `aiohttp` and all transitive dependencies to reviewed versions. - Use a lock file with cryptographic hashes and install with hash verification. - Configure an explicit trusted package index rather than inheriting arbitrary pip settings. - Invoke pip through the selected interpreter, for example `python3 -m pip`, to avoid interpreter mismatch. - Do not silently alter the active global Python environment. - Record dependency versions and provide a controlled update procedure. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
log_viewer.py:180
Finding
Sensitive Conversation Export Delegated to an Unverified External Script<![CDATA[ ## Vulnerability Details **File Location**: `log_viewer.py:35`, `log_viewer.py:180-207` **Vulnerability Type**: Execution of an external data-export component without integrity validation **Risk Level**: Medium ### Vulnerable Code ```python FEISHU_WRITE = Path("/Users/xm_plus/.openclaw/workspace/company/feishu_write.py") ``` ```python def call_feishu_write(title, md_content, timeout=120): """Call feishu_write.py to create a Feishu document.""" tmp = tempfile.NamedTemporaryFile( mode="w", suffix=".md", delete=False, prefix="/tmp/lobster_log_", encoding="utf-8" ) tmp.write(md_content) tmp.close() link = None for attempt in range(1, 4): try: result = subprocess.run( ["python3", str(FEISHU_WRITE), title, tmp.name], capture_output=True, text=True, timeout=timeout ) if result.returncode == 0: link = result.stdout.strip() break else: print(f"Feishu document creation failed: {result.stderr[:200]}") except subprocess.TimeoutExpired: print("Feishu write timed out; retrying") except Exception as ex: print(f"Feishu write exception: {ex}") try: os.unlink(tmp.name) except Exception: pass return link ``` ### Technical Analysis When the user explicitly supplies `--feishu`, the viewer writes log-derived content to a temporary Markdown file and executes `feishu_write.py`, which is outside this audited package. The external script is neither bundled nor integrity-checked, and its hard-coded path is specific to the original developer's environment. The subprocess invocation uses an argument array rather than a shell, so no command-injection issue was identified in the shown call. Python's `NamedTemporaryFile` also normally creates a securely randomized, owner-restricted file. The primary risk is that complete conversat ...[truncated 1344 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Bundle and audit the exporter or define it as a separately installed, versioned dependency. - Make the exporter path configurable instead of using a developer-specific absolute path. - Verify the external script's ownership, permissions, and cryptographic digest before execution. - Display the export destination and request explicit confirmation before transmitting conversation content. - Allow users to review and redact the generated document before upload. - Minimize exports by default and avoid including complete prompts or responses unless specifically selected. - Continue using argument-array subprocess execution; do not replace it with shell invocation. - Ensure temporary files remain owner-only and delete them in a `finally` block. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (52)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented purpose is local API logging and viewing, but the skill also exposes log export to Feishu through an external helper and network-affecting behavior not clearly disclosed in the top-level description. Because the logs contain full prompts and conversations, this mismatch can mislead users into sending sensitive data to an external service they did not expect to be involved.

Ssd 3

High
Confidence
98% confidence
Finding
The skill is explicitly designed to record complete prompts, generations, and token usage, which creates a direct data exposure path for highly sensitive natural-language content. In an LLM tooling context, that content can include secrets, proprietary code, credentials, personal data, and hidden system prompts, so comprehensive capture materially raises confidentiality risk.

Ae1

High
Category
analysis-evasion
Content
**文件:** `log-viewer.html`(skill 目录内)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
**文件:** `log-viewer.html`(skill 目录内)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
**文件:** `log-viewer.html`(skill 目录内)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ssd 3

High
Confidence
97% confidence
Finding
The viewer documentation specifically promotes displaying complete system prompts and multi-turn conversations in the UI, increasing the likelihood of accidental disclosure through local shoulder-surfing, screenshots, screen sharing, or copied exports. Because system prompts and chat history often contain hidden instructions and confidential user content, this goes beyond harmless observability.

Ssd 3

High
Confidence
99% confidence
Finding
The documented log schema includes storage of full request bodies with system and message content, which is a strong indicator of persistent storage of sensitive conversational data. Persistent full-fidelity storage substantially increases blast radius if the logs are accessed by other users, malware, backups, or external export features.

Missing User Warnings

High
Confidence
96% confidence
Finding
This proxy is explicitly designed to intercept and persist full LLM request and response bodies, which commonly contain sensitive prompts, system instructions, user data, secrets, and model outputs. Even though auth headers are partially masked, the body logging creates a substantial confidentiality risk because sensitive content is stored in cleartext and can be exposed through local compromise, backups, or later sharing of logs.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly promotes logging complete prompts, system prompts, generations, and token usage, but does not prominently warn that this can capture secrets, credentials, personal data, proprietary prompts, or regulated data. In this skill context, the proxy transparently intercepts all LLM traffic, making the privacy risk materially higher because users may not realize the full sensitivity and breadth of what is stored.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
Documenting one-click Feishu export of full logged conversations without a clear warning about external sharing materially increases the chance of sensitive data exfiltration. Because the logged content includes complete prompts and model outputs, exporting it to a collaboration platform can expose confidential business data, secrets, or personal information to broader audiences or third-party systems.

Session Persistence

Medium
Category
Rogue Agent
Content
- 复制 `proxy.py` 和 `log_viewer.py` 到 `~/.openclaw/workspace/company/api-proxy/`
- 创建日志目录 `~/.openclaw/workspace/company/api-logs/`
- 检查并安装 `aiohttp` 依赖
- 写入 LaunchAgent plist(`~/Library/LaunchAgents/com.lobster.api-proxy.plist`)
- 加载 plist,启动后台代理服务

### 2. 手动配置(重要!)
Confidence
91% confidence
Finding
The README instructs users to install a LaunchAgent plist that starts the proxy as a background service, creating persistence across sessions. In this context, persistent transparent interception of all LLM API calls is security-relevant because it continuously collects sensitive prompts and responses beyond a single troubleshooting session.

Session Persistence

Medium
Category
Rogue Agent
Content
- 创建日志目录 `~/.openclaw/workspace/company/api-logs/`
- 检查并安装 `aiohttp` 依赖
- 写入 LaunchAgent plist(`~/Library/LaunchAgents/com.lobster.api-proxy.plist`)
- 加载 plist,启动后台代理服务

### 2. 手动配置(重要!)
Confidence
91% confidence
Finding
Loading the LaunchAgent to start a background proxy establishes ongoing session persistence. While persistence is not inherently malicious, in a skill that transparently logs complete LLM traffic it increases exposure by continuously operating after installation and possibly after the user forgets it is enabled.

Session Persistence

Medium
Category
Rogue Agent
Content
修改后需要重新加载 LaunchAgent:

```bash
launchctl unload ~/Library/LaunchAgents/com.lobster.api-proxy.plist
launchctl load ~/Library/LaunchAgents/com.lobster.api-proxy.plist
```
Confidence
89% confidence
Finding
The documented use of launchctl to manage the plist confirms the proxy is intended to persist as a user agent. In this skill context, persistence magnifies the sensitivity of the logging capability because it enables long-lived monitoring of conversations and prompts.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
launchctl unload ~/Library/LaunchAgents/com.lobster.api-proxy.plist
launchctl load ~/Library/LaunchAgents/com.lobster.api-proxy.plist
```

### 3. 重启 Gateway(与用户确认后)
Confidence
88% confidence
Finding
This duplicate persistence reference again indicates a user-level autostart mechanism via plist. In a logging proxy, autostart is more dangerous than a typical helper utility because it silently resumes interception after login unless the user actively disables it.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
launchctl unload ~/Library/LaunchAgents/com.lobster.api-proxy.plist
launchctl load ~/Library/LaunchAgents/com.lobster.api-proxy.plist
```

### 3. 重启 Gateway(与用户确认后)
Confidence
88% confidence
Finding
This duplicate persistence reference again indicates a user-level autostart mechanism via plist. In a logging proxy, autostart is more dangerous than a typical helper utility because it silently resumes interception after login unless the user actively disables it.

Session Persistence

Medium
Category
Rogue Agent
Content
5. **日志大小**:流式请求会额外保存原始 SSE 数据(`response_body_raw_stream`),长对话的日志条目可能较大。

6. **端口冲突**:默认端口 18790,如需修改,同时更新 plist 和 `openclaw.json` 中的 `baseUrl`。

---
Confidence
75% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
└── proxy.stderr.log  # 代理服务错误日志

~/Library/LaunchAgents/
└── com.lobster.api-proxy.plist  # 开机自启动配置
```

---
Confidence
90% confidence
Finding
Listing the LaunchAgents plist as an installed runtime artifact confirms an autostart persistence mechanism. In the context of a transparent API logging tool, this matters because it normalizes a background monitoring component that survives reboots/logins and may continue recording sensitive traffic without ongoing user awareness.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises and documents behaviors that involve filesystem writes, network access, shell execution, and persistent installation, but it does not declare any explicit tool scope or permission boundaries. That makes the capability set less transparent to users and reviewers, increasing the chance that sensitive operations are approved or invoked without informed consent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill emphasizes debugging and visualization benefits but does not present a prominent privacy warning that it records complete prompts, generations, and conversation contents. Since LLM traffic often includes credentials, internal instructions, or personal data, users may enable the logger without understanding the sensitivity of what will be stored.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
A terminal viewer for local log inspection includes document publishing to Feishu, which expands the trust boundary from local analysis to third-party data transmission. In this context, the feature is especially risky because the underlying logs are described as containing complete prompts, responses, and user inputs.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The installation guidance configures a startup-persistent transparent proxy and redirects API traffic through it, but it does not prominently warn that this changes system behavior and causes ongoing interception and logging of requests. That makes the setup more dangerous in context because it can silently affect all future LLM traffic after initial installation.

Session Persistence

Medium
Category
Rogue Agent
Content
1. 创建 `~/.openclaw/workspace/company/api-proxy/`
2. 复制 `proxy.py` 和 `log_viewer.py`
3. 创建日志目录 `~/.openclaw/workspace/company/api-logs/`
4. 写入 macOS LaunchAgent plist(开机自启动)
5. 启动代理服务

### 配置(安装后手动完成)
Confidence
90% confidence
Finding
The skill installs a macOS LaunchAgent plist for automatic startup, creating persistence for a component that intercepts and logs API traffic. Persistence is more dangerous here because it can continue collecting sensitive prompt and response data across sessions even after the user forgets it was enabled.

Session Persistence

Medium
Category
Rogue Agent
Content
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.openclaw/workspace/company/api-proxy"
LOG_DIR="$HOME/.openclaw/workspace/company/api-logs"
PLIST_PATH="$HOME/Library/LaunchAgents/com.lobster.api-proxy.plist"
PROXY_PORT=18790
UPSTREAM="http://model.mify.ai.srv/anthropic"
Confidence
88% confidence
Finding
This duplicate finding also points to the LaunchAgent plist path, which is part of implementing login-session persistence. Persistent execution of a request-logging proxy increases the chance of prolonged collection of sensitive prompt/output data and makes accidental over-collection more likely.

Session Persistence

Medium
Category
Rogue Agent
Content
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.openclaw/workspace/company/api-proxy"
LOG_DIR="$HOME/.openclaw/workspace/company/api-logs"
PLIST_PATH="$HOME/Library/LaunchAgents/com.lobster.api-proxy.plist"
PROXY_PORT=18790
UPSTREAM="http://model.mify.ai.srv/anthropic"
Confidence
88% confidence
Finding
This duplicate finding also points to the LaunchAgent plist path, which is part of implementing login-session persistence. Persistent execution of a request-logging proxy increases the chance of prolonged collection of sensitive prompt/output data and makes accidental over-collection more likely.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The installer automatically executes `pip3 install aiohttp`, which downloads and runs code from the network during installation without prior approval, pinning, or integrity verification. Even though `aiohttp` may be a legitimate dependency for the proxy, silent dependency installation expands the trust boundary and exposes users to supply-chain risk.

Static analysis

No suspicious patterns detected.