T05 · Unauthorized Access and Privilege Escalation
- Location
QMT-TradingClaw/backtests/monitor_server.py:469- Finding
Unauthenticated Public Monitoring and Control API
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a disclosed quantitative trading assistant, but it combines live-trading authority with under-scoped monitor, credential, and process-control behavior that users should review before installing.
Install only if you are comfortable with an agent that can generate and run strategy code, expose a monitoring service, and start QMT simulated or live trading. Use a disposable or scoped QGData token, avoid relying on global .env files, bind the monitor to localhost or protect it with authentication, and require your own manual confirmation before any QMT trade or probe order.
QMT-TradingClaw/backtests/monitor_server.py:469Unauthenticated Public Monitoring and Control API
QMT-TradingClaw/backtests/pipeline_orchestrator.py:1754QGData Token Disclosed Through Child-Process Command-Line Arguments
QMT-TradingClaw/backtests/qg_constants.py:5Hard-Coded Shared QGData Credential Distributed in Source
QMT-TradingClaw/backtests/pipeline_orchestrator.py:98Credential Discovery Reads Global Agent and System Configuration Files
QMT-TradingClaw/backtests/monitor_server.py:44Third-Party JavaScript Executes Without Integrity Verification
QMT-TradingClaw/backtests/monitor_server.py:663Monitor Startup Can Force-Kill Unrelated Processes Owning a Port
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def _url(path): return Path(path).resolve().as_uri()
def _report(path, **kw):
if not MONITOR: return
try: urlopen(f"{MONITOR}{path}?{urlencode(kw, quote_via=quote)}", timeout=2)
except Exception as e: p(f"[monitor-warn] report{path} failed: {e}")
def _report_post(path, data):
if not MONITOR: return
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
except Exception as e: p(f"[monitor-warn] report{path} failed: {e}")
def _report_post(path, data):
if not MONITOR: return
try: urlopen(Request(f"{MONITOR}{path}", json.dumps(data, ensure_ascii=False).encode(), {"Content-Type": "application/json"}), timeout=5)
except Exception as e: p(f"[monitor-warn] post{path} failed: {e}")
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def _read_monitor_state_by_port(port: int, timeout: float = 0.8) -> Optional[Dict[str, Any]]:
try:
with urlopen(f"http://127.0.0.1:{int(port)}/api/state", timeout=timeout) as resp:
data = json.loads(resp.read().decode("utf-8", errors="ignore"))
return data if isinstance(data, dict) else None
except Exception: return None
The code explicitly searches multiple filesystem locations for a credential and classifies whether it found a personal or shared token, which is credential-access behavior beyond what a simple capability check should need. In a skill execution environment, this is more dangerous because the agent may run with access to developer or host files, allowing the skill to leverage secrets the user did not intentionally provide for this run.
return ""
def _token_context() -> str:
env_tok = (os.getenv("QGDATA_TOKEN", "") or _read_env_value_from_files("QGDATA_TOKEN", [_PROJECT_ROOT / ".env", Path.home() / ".openclaw" / ".env", Path("/opt/.env")])).strip()
if not env_tok: return "missing" #未传token,将回退共享token
if env_tok == QGDATA_SHARED_TOKEN: return "shared"
return "personal"
Before starting, the server probes the chosen port and force-terminates whatever local process is listening there, regardless of ownership or purpose. This creates an arbitrary local denial-of-service primitive: invoking the monitor on a busy port can kill unrelated developer tools, databases, or other sensitive services. Within this skill, that behavior is especially unsafe because it is embedded in normal startup rather than an exceptional admin workflow.
This line turns a user-controllable operational parameter (port) into a destructive system action by passing it to a shell pipeline that kills listeners on that port. Even with integer validation reducing injection risk, it still constitutes tool-parameter abuse because a routine startup option can be used to terminate arbitrary local services. In the context of an agent-managed trading skill, such host-level disruption is disproportionate and dangerous.
f"(Get-NetTCPConnection -LocalPort {port} -State Listen -ErrorAction SilentlyContinue).OwningProcess | Sort-Object -Unique | ForEach-Object {{ Stop-Process -Id $_ -Force -ErrorAction SilentlyContinue }}"],
timeout=8, capture_output=True, text=True)
else:
subprocess.run(f"lsof -ti:{port} | xargs -r kill -9 2>/dev/null || fuser -k {port}/tcp 2>/dev/null", shell=True, timeout=5, capture_output=True, text=True)
except Exception: pass
time.sleep(1.5 if is_win else 0.5)
try:
The code harvests credentials from multiple .env locations, including the project root, user home, and /opt, and falls back to a shared token. While common operationally, this broad secret discovery behavior is sensitive because it expands where the skill looks for credentials and can normalize use of shared secrets in a module that executes strategy-related code.
env_token = os.getenv("QGDATA_TOKEN", "")
if env_token:
return env_token, "env"
file_token = read_env_value_from_files("QGDATA_TOKEN", [PROJECT_ROOT / ".env", Path.home() / ".openclaw" / ".env", Path("/opt/.env")])
if file_token:
return file_token, "env"
return QGDATA_SHARED_TOKEN, "shared"
This helper defaults to passing the entire parent environment to all spawned subprocesses. In an orchestrator that launches monitor, worker, backtest, and trade-related helpers, this creates systematic secret overexposure across multiple child execution boundaries.
return subprocess.Popen(
command,
cwd=str(PROJECT_ROOT),
env=env or os.environ.copy(),
stdout=f,
stderr=subprocess.STDOUT,
start_new_session=True,
The worker process inherits a full copy of the parent environment, which can expose unrelated secrets, API keys, cloud credentials, and internal configuration to child processes that later load or execute strategy code. In this module, user-provided or generated strategy code is compiled/imported and a backtest runner is launched, so broad environment inheritance increases the blast radius of any malicious or compromised strategy.
store.mark_step(state, "monitor", "success", "monitor started and requirement posted")
worker_cmd = [payload["python_bin"], str(Path(__file__).resolve()), "worker", "--run-id", run_id]
worker_env = os.environ.copy()
if resolved_token:
worker_env["QGDATA_TOKEN"] = resolved_token
worker_env["QGDATA_TOKEN_SOURCE"] = token_source
The dry-run subprocess receives the full ambient environment plus project variables. Because the subprocess loads strategy modules and data tooling, any inherited secrets become accessible to code running in that child context, which is especially risky for an assistant that processes externally influenced strategy files.
if payload.get("start"): _dry_cmd.extend(["--start", payload["start"]])
if payload.get("end"): _dry_cmd.extend(["--end", payload["end"]])
if qgdata_token: _dry_cmd.extend(["--token", qgdata_token])
_dry_env = {**os.environ, "QUANTCLAW_ROOT": str(PROJECT_ROOT), "QMT_PROJECT_ROOT": str(PROJECT_ROOT)}
_dry_log = store.run_dir / "dryrun.log"
_dry_proc = start_process(_dry_cmd, _dry_log, env=_dry_env)
_dry_timeout = 120
The main backtest runner is launched with the full environment, exposing all parent-process secrets to a process that imports and executes strategy code. Given the skill's strategy-generation and trading-adjacent functionality, this materially increases the consequence of malicious strategy content or a compromised helper.
cmd.extend(["--token", qgdata_token])
run_log_path = store.run_dir / "backtest.log"
proc = start_process(cmd, run_log_path, env={**os.environ, "QUANTCLAW_ROOT": str(PROJECT_ROOT), "QMT_PROJECT_ROOT": str(PROJECT_ROOT)})
state["process"]["backtest_pid"] = proc.pid
store.save(state)
This file goes beyond backtesting orchestration and includes commands to start and stop simulated/live trading. That materially increases the risk surface because a skill marketed as a strategy assistant can now place or facilitate real market actions, making misuse or prompt-driven activation much more dangerous.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
env_file = PROJECT_ROOT / ".env"
if env_file.exists():
_warn(".env 文件", str(env_file), "已存在")
else:
example = PROJECT_ROOT.parent / ".env.example"
hint = f"不存在。建议: cp {example} {env_file} 然后编辑" if example.exists() else "不存在。建议创建 .env 文件配置环境变量"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
env_file = PROJECT_ROOT / ".env"
if env_file.exists():
_warn(".env 文件", str(env_file), "已存在")
else:
example = PROJECT_ROOT.parent / ".env.example"
hint = f"不存在。建议: cp {example} {env_file} 然后编辑" if example.exists() else "不存在。建议创建 .env 文件配置环境变量"
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
env_file = PROJECT_ROOT / ".env"
if env_file.exists():
_warn(".env 文件", str(env_file), "已存在")
else:
example = PROJECT_ROOT.parent / ".env.example"
hint = f"不存在。建议: cp {example} {env_file} 然后编辑" if example.exists() else "不存在。建议创建 .env 文件配置环境变量"
The probe command performs an order/cancel validation path against trading infrastructure, which is a powerful side-effecting capability unrelated to ordinary strategy orchestration. In this context, even a 'test' order can have financial, compliance, or operational consequences if misconfigured or pointed at a live environment.
The README states that live orders do not require secondary confirmation, while presenting only configurable risk limits as safeguards. In a system that uses LLM-generated strategies and automated execution, removing confirmation materially increases the chance of unintended real-money trades, especially from prompt mistakes, logic bugs, or adversarial inputs.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
This skill includes direct simulated/live trading actions, probe order placement and cancellation, local installation discovery, dynamic loading of Python strategy files, and state writes. When such capabilities are not prominently disclosed and tightly gated, an agent can trigger real financial actions or execute untrusted strategy code with significant operational and financial consequences.
No suspicious patterns detected.