T05 · Unauthorized Access and Privilege Escalation
- Location
scheduler.py:49- Finding
Unauthenticated Public Endpoint Triggers Privileged Drift-Detection Operations
- Content
View full analysis
Vulnerability Details
File Location:
scheduler.py:49-59
Vulnerability Type: Missing authentication and authorization on a state-changing endpoint
Risk Level: HighVulnerable Code
python @app.route("/run-check") def run_check(): """HTTP endpoint for OpenClaw to trigger a manual drift check.""" logger.info("[scheduler] Manual /run-check triggered via HTTP") try: result = skill_run() return jsonify({"status": "ok", "result": result}) except Exception as exc: logger.error(f"[scheduler] /run-check failed: {exc}", exc_info=True) return jsonify({"status": "error", "message": str(exc)}), 500The endpoint is exposed through the public web service configured in
render.yaml:2-6:yaml services: - type: web name: superwise-drift-detection-skill env: python buildCommand: pip install -r requirements.txt startCommand: python scheduler.pyTechnical Analysis
The
/run-checkroute performs no authentication, authorization, request-signature validation, or source restriction. It also uses HTTPGETfor an operation with substantial side effects.Every request invokes
skill_run(), which:- Fetches records from the configured inference endpoint.
- Uploads those records to Superwise.
- Assigns fresh UUIDs to records, preventing natural deduplication between runs.
- Triggers and polls configured drift policies.
- Sends a Telegram notification.
Because the included Render configuration deploys
scheduler.pyas a web service, the endpoint is expected to be reachable from the internet unless external access controls are added separately. There is also no rate limit, concurrency guard, or idempotency control.The exception handler returns
str(exc)directly to the remote caller. Depending on the failure, this may disclose internal URLs, third-party response details, dataset identifiers, or opera ...[truncated 1329 chars]- Remediation
View remediation
Remediation Suggestions
- Replace the state-changing
GETroute with aPOSTroute. - Require authentication using either:
- A high-entropy bearer token stored as a deployment secret.
- A cryptographically verified OpenClaw webhook signature.
- Mutual TLS or an identity-aware reverse proxy.
- Compare authentication tokens using a constant-time comparison.
- Restrict the endpoint to trusted source networks where deployment infrastructure permits it.
- Add per-client and global rate limits.
- Add a process-wide or distributed lock so only one drift check can run at a time.
- Introduce idempotency controls to prevent duplicate ingestion.
- Queue long-running checks asynchronously and return
202 Acceptedrather than occupying the web request. - Return a generic error response to callers and retain detailed exceptions only in protected server logs.
- Ensure monitoring alerts distinguish scheduled checks from authenticated manual checks.
- Replace the state-changing
