LLM Proxy
The skill acts as an unauthenticated local proxy forwarding user API credentials to external LLM providers, with a content-security layer that declares blocking but only logs critical alerts (including credential theft and reverse shell patterns), creating a deceptive security illusion.
content-filter-rules.json defines CRED-001 (sk-, AKIA-, ghp_, api_key patterns) as severity=critical, but response_actions.critical.block=false. The proxy will log credential-theft attempts but forward the actual request to the upstream LLM provider, meaning stolen API keys go through the proxy.
scripts/content-filter-rules.json:217 Why this conclusion was reached
2/4 dimensions flagged4 undeclared or violating capabilities were inferred.
25 lower-risk artifacts were extracted and still need context.
The report includes 5 attack-chain steps and 5 severe findings.
Dependencies are present but no obvious high-risk issue stands out.
Attack Chain
Entry · SKILL.md:17
Escalation · scripts/llm-proxy-ctl.sh:34
Escalation · scripts/llm-proxy.py:482
Escalation · scripts/llm-proxy.py:259
Impact · scripts/content-filter-rules.json:217
What drove the risk score up
SKILL.md does not mention subprocess, shell, or process management; llm-proxy-ctl.sh uses kill/kill_by_port
SKILL.md does not declare opening a TCP port or running a persistent background service
Proxy forwards user Authorization/API-Key headers to external providers with no auth check; any local process can use the proxy
response_actions block=false for critical severity — credential exfiltration and reverse shell patterns only logged, not blocked
SKILL.md states '严重违规时阻断响应' but code sets block=false for all severity levels including critical
Most important evidence
Critical content-blocking disabled — credential exfiltration not prevented
content-filter-rules.json defines CRED-001 (sk-, AKIA-, ghp_, api_key patterns) as severity=critical, but response_actions.critical.block=false. The proxy will log credential-theft attempts but forward the actual request to the upstream LLM provider, meaning stolen API keys go through the proxy.
scripts/content-filter-rules.json:217 API key forwarding without authorization
The proxy blindly forwards the Authorization and X-Api-Key headers from incoming requests directly to upstream LLM providers. Any local process can send requests with arbitrary credentials through this proxy. Combined with block=false on credential detection, a stolen API key can be routed through this proxy.
scripts/llm-proxy.py:259 Documentation claims blocking, code does not block
SKILL.md states: '严重违规时阻断响应并返回错误' (blocks on serious violations) and README states '内容安全检测仅记录和提醒,不自动拦截(可配置)' — both contradictory. The code sets block=false for all severity levels. This is a doc-to-code mismatch.
SKILL.md:99 Undeclared persistent background service
SKILL.md does not mention that the skill runs a persistent background daemon, opens a TCP port, or manages processes. The llm-proxy-ctl.sh starts a daemon via backgrounding (&) and writes to /tmp/llm-proxy.pid. This is not declared.
scripts/llm-proxy-ctl.sh:34 Undeclared shell and process management capabilities
SKILL.md declares no shell execution, but llm-proxy-ctl.sh uses kill, kill -9, lsof, curl, mkdir, and background process management. SKILL.md also declares no filesystem WRITE, but scripts write to ~/.openclaw/logs/ and /tmp/.
scripts/llm-proxy-ctl.sh:1 SIGUSR1 debug handler exposes full thread stacks
llm-proxy.py registers signal.SIGUSR1 which, when triggered, prints full thread stacks including any sensitive data in stack frames. This could leak internal state, credentials in variables, or request content.
scripts/llm-proxy.py:471 Verbose request/response logging to user-writable directory
All requests and responses (including message content, provider, request_id, status) are written to ~/.openclaw/logs/llm-proxy/proxy-YYYY-MM-DD.jsonl. While Authorization headers are redacted, the response content and full request metadata are logged. This creates a local data trail.
scripts/llm-proxy.py:361 No dependencies declared — no requirements.txt or package.json
The skill uses only Python standard library (json, re, time, os, sys, signal, traceback, uuid, threading, datetime, http.server, socketserver, urllib). No third-party dependencies, which reduces supply chain risk. However, subprocess is not declared as a dependency since it's used in shell scripts.
scripts/llm-proxy.py:1 Declared capability vs actual capability
SKILL.md:1 — SKILL.md declares no network access, but the proxy opens TCP port 18888 and makes outbound HTTP requests to 22+ external LLM provider APIs llm-proxy-ctl.sh:34,47 — Uses lsof, kill, kill -9, backgrounding python3; SKILL.md makes no mention of subprocess or shell usage llm-proxy-ctl.sh:35 — mkdir -p for log dirs; llm-proxy.py:89 — writes to ~/.openclaw/logs/ llm-proxy.py:34-37 — reads LLMPROXY_CONFIG, LLM_PROXY_PORT, RULES_FILE from os.environ Suspicious artifacts and egress
http://127.0.0.1:18888/health README.md:116
https://api.your-provider.com/v1 README.md:147
http://127.0.0.1:18888/your-provider/chat/completions README.md:156
https://api.your-provider.com/v1/chat/completions README.md:157
http://127.0.0.1:18888/openai/chat/completions README.md:259
http://127.0.0.1:18888/bailian/chat/completions README.md:272
https://api.groq.com/openai/v1 scripts/llm-proxy-config.json:49
https://api.cloudflare.com/client/v4/accounts scripts/llm-proxy-config.json:55
https://api.deepseek.com/v1 scripts/llm-proxy-config.json:61
https://api.moonshot.cn/v1 scripts/llm-proxy-config.json:67
https://open.bigmodel.cn/api/paas/v4 scripts/llm-proxy-config.json:73
https://api.siliconflow.cn/v1 scripts/llm-proxy-config.json:79
Dependencies and supply chain
| Package | Version | Source | Known vuln | Notes |
|---|---|---|---|---|
| Python standard library only | N/A | stdlib | No | Uses only json, re, time, os, sys, signal, threading, http.server, socketserver, urllib — no pip packages needed |
File composition
scripts/llm-proxy.py scripts/content-filter-rules.json README.md scripts/llm-proxy-config.json scripts/llm-proxy-ctl.sh SKILL.md