T09 · Insecure Skill Coding Practices
- Location
web_server.py:173- Finding
Unauthenticated loopback API exposes trading credentials and privileged bot controls
- Content
View full analysis
Vulnerability Details
File Location:
web_server.py, lines 173–233 and 260
Vulnerability Type: Unauthenticated sensitive-data disclosure and state-changing API access
Risk Level: HighTechnical Analysis
The web control panel binds to the loopback interface, but its API has no authentication, authorization, CSRF protection, or validation of the
HostandOriginheaders.The configuration endpoint returns every value loaded from
.env, includingPAPER_WALLET_PRIVATE_KEY,PAPER_SESSION_KEY,ONDO_KEY_ID, andONDO_API_SECRET:python def do_GET(self): parsed = urlparse(self.path) path = parsed.path if path == "/" or path == "/index.html": if HTML_FILE.exists(): self._send_html(HTML_FILE.read_text(encoding="utf-8")) else: self._send_html("<h1>index.html not found</h1>", 404) return if path == "/api/config": self._send_json({"success": True, "config": load_env()}) return if path == "/api/status": running = is_running() pid = get_pid() self._send_json({ "success": True, "running": running, "pid": pid, "log": tail_log(150), }) return if path == "/api/log": self._send_json({"success": True, "log": tail_log(300)}) returnThe POST API also permits callers to overwrite the entire
.envconfiguration and start or stop the bot without proving that they are the authorized operator:python def do_POST(self): parsed = urlparse(self.path) path = parsed.path length = int(self.headers.get("Content-Length", 0)) body = self.rfile.read(length).decode("utf-8") if length else "{}" try: data = json.loads(body) except json.JSONDecodeError: data = {} if path == "/api/config": try: s ...[truncated 3018 chars]- Remediation
View remediation
Remediation Suggestions
- Generate a cryptographically random control token for each server launch and require it on every API request. Store it outside the served page or deliver it through a secure initialization mechanism.
- Validate the
Hostheader against an exact allowlist such as127.0.0.1:8765andlocalhost:8765; reject all other values to mitigate DNS rebinding. - Validate
Originon all state-changing requests and reject missing or unexpected origins where appropriate. - Add CSRF protection to every configuration and process-control endpoint.
- Never return raw secret values from
/api/config. Return only non-sensitive settings and masked indicators such as whether each credential is configured. - Split secret updates from ordinary strategy configuration. Require explicit re-entry and authenticated confirmation when changing credentials.
- Allowlist accepted configuration keys and validate their types and ranges server-side before writing
.env. - Require a separate explicit confirmation for switching to real mode and starting real trades. The backend must enforce this gate rather than relying only on browser UI warnings.
- Apply restrictive filesystem permissions to
.envand avoid exposing exception messages that could reveal sensitive local details. - Consider replacing the browser-accessible HTTP interface with a local authenticated IPC mechanism, or use a framework with established session, CSRF, origin, and host-validation controls.
