T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/openlist.py:470
- Finding
- Operation plans are unsigned, mutable, replayable, and do not enforce expiration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openlist.py`, lines 470-524 and 551-580 **Vulnerability Type**: Unauthenticated operation plan / replay weakness **Risk Level**: High ### Vulnerable Code ```python def validate_plan_schema(plan: Dict[str, Any], config: Dict[str, Any]) -> Dict[str, Any]: if not isinstance(plan, dict): raise UserFacingError("Plan file must contain a JSON object.") required = ["plan_id", "request_id", "created_at", "type", "api", "prechecks", "conflicts", "risk", "resolved"] missing = [field for field in required if field not in plan] if missing: raise UserFacingError("Plan file is missing required fields: %s." % ", ".join(missing)) plan_type = plan.get("type") if plan_type not in ALLOWED_PLAN_TYPES: raise UserFacingError("Unsupported plan type: %s." % plan_type) api = plan.get("api") or {} if not isinstance(api, dict) or api.get("base_url") != config.get("base_url"): raise UserFacingError( "Plan base_url does not match the current OPENLIST_BASE_URL.", hints=["Re-run the preview command against the same OpenList instance and use the new plan file."], ) resolved = plan.get("resolved") if not isinstance(resolved, dict): raise UserFacingError("Plan resolved section must be an object.") endpoint = resolved.get("endpoint") if endpoint not in ALLOWED_ENDPOINTS: raise UserFacingError("Plan endpoint is not allowed: %s." % endpoint) if endpoint != PLAN_ENDPOINTS.get(plan_type): raise UserFacingError("Plan endpoint does not match the plan type: %s." % endpoint) findings = scan_for_dangerous_signals(plan) if findings: raise UserFacingError( "Plan validation failed because it contains unsafe fields.", data={"findings": findings}, hints=["Generate a fresh preview plan instead of editing the plan file by hand."], ) prechecks = pla ...[truncated 4769 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Sign every generated plan using an HMAC or asymmetric signature covering all security-relevant fields, including: - `plan_id`, `request_id`, `created_at`, and `expires_at`. - Operation type and base URL. - The complete request and resolved body. - Endpoint, prechecks, conflicts, risk data, and resolved extras. 2. Verify the signature using constant-time comparison before processing any plan field during `apply`. 3. Parse and enforce `expires_at`; reject missing, malformed, or expired plans. 4. Store consumed plan IDs in a protected state file or database and reject replay attempts. 5. Validate each operation body's exact schema rather than only scanning for dangerous key names. 6. Cross-check all resolved fields against the original request fields for move, rename, and offline-download operations, as is partially done for deletion. 7. Re-run online preconditions immediately before every mutation, including source existence, target state, and conflict detection. 8. Create plan files atomically with restrictive permissions and document that they must not be stored in shared or world-writable directories. ]]>
