T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- src/handler.py:20
- Finding
- Spoofable Caller Authorization Allows Impersonation of Privileged Operators<![CDATA[ ## Vulnerability Details **File Location**: `src/handler.py:20-45` **Vulnerability Type**: Untrusted caller identity used as an authorization credential **Risk Level**: High ### Vulnerable Code ```python def _allowed_callers() -> set[str]: raw = os.environ.get("OPENCLAW_ALLOWED_CALLERS", "architect,chief-of-staff") out = set() for part in raw.split(","): v = part.strip() if v: out.add(v) return out def authorize(task: dict) -> tuple[bool, str]: action = str(task.get("action", "")).strip() caller = str(task.get("caller", "")).strip() if not caller: return False, "missing caller" allowed = _allowed_callers() if caller not in allowed: return False, f"caller '{caller}' not authorized" if action in HIGH_RISK_ACTIONS: allow_high_risk = os.environ.get("OPENCLAW_ALLOW_HIGH_RISK", "0") == "1" if not allow_high_risk: return False, f"action '{action}' blocked (set OPENCLAW_ALLOW_HIGH_RISK=1 to enable)" return True, "ok" ``` The task schema also defines `caller` as an ordinary task-controlled string: ```json { "properties": { "task_id": {"type":"string"}, "action": {"type":"string"}, "params": {"type":"object"}, "caller": {"type":"string"}, "correlation_id": {"type":"string"} } } ``` ### Technical Analysis The authorization decision treats the `caller` value embedded in the submitted JSON document as proof of identity. Because the same party submitting or modifying a task can choose this field, an attacker can claim to be any name in `OPENCLAW_ALLOWED_CALLERS`, including the default privileged identities `architect` and `chief-of-staff`. No cryptographic signature, authenticated transport identity, trusted gateway assertion, token, file ownership check, or other mechanism binds the claimed caller to a verified principal. The handler also does not validate the task against `schemas/task.schema.json`, although schema ...[truncated 1814 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not accept `caller` in the task body as an authentication credential. 2. Derive caller identity from a trusted execution context, such as: - Mutually authenticated transport metadata. - A verified gateway identity. - A signed task envelope using a trusted caller key. - A protected local IPC mechanism with operating-system peer credentials. 3. Bind the verified identity to the task body, action, parameters, timestamp, and nonce. 4. Add expiration and replay protection to signed or authenticated tasks. 5. Reject discrepancies between informational caller fields and the authenticated identity. 6. Apply authorization after authentication and before any filesystem writes or action dispatch. 7. Validate tasks against a strict schema with `additionalProperties: false`, action-specific parameter schemas, size limits, and identifier constraints. 8. Replace privileged default caller names with an explicit fail-closed configuration where appropriate. 9. Restrict task-file permissions and verify file ownership if filesystem-based task ingestion remains supported. ]]>
