T09 · Insecure Skill Coding Practices
Error
- Location
- warden_governance/sentinel_client.py:34
- Finding
- Governance decisions can be bypassed through an under-scoped authorization cache<![CDATA[ ## Vulnerability Details **File Location**: `warden_governance/sentinel_client.py:34-48, 107-111`; related policies in `policies/openclaw_default.yaml:11-24, 27-40, 51-60` **Vulnerability Type**: Authorization decision cache confusion **Risk Level**: Critical ### Vulnerable Code ```python def get(self, action_type: str, env: str) -> CheckResult | None: key = f"{action_type}:{env}" entry = self._cache.get(key) if entry is None: self._misses += 1 return None if time.time() - entry["cached_at"] > self._ttl: del self._cache[key] self._misses += 1 return None self._hits += 1 return entry["result"] def set(self, action_type: str, env: str, result: CheckResult) -> None: if result.decision != Decision.ALLOW: return key = f"{action_type}:{env}" self._cache[key] = {"result": result, "cached_at": time.time()} ``` The cached result is returned before policy evaluation: ```python env = action.context.get("env", "dev") cached = self.cache.get(action.type.value, env) if cached is not None: return cached ``` The affected policies distinguish operations using fields that are absent from the cache key: ```yaml - name: protect-email-delete match: action.type: data.write action.data.openclaw_original: email.delete decision: review - name: protect-file-delete match: action.type: data.write action.data.openclaw_original: file.delete decision: review - name: review-payments match: action.type: api.call action.data.openclaw_original: payment.create decision: review ``` ### Technical Analysis The cache key contains only the normalized action type and environment. However, policy evaluation also depends on the original OpenClaw action, action data, service, data classification, agent identity, and arbitrary context fields. Several different operations are normalized to the same governance type. For example, `file.write`, `email.delete`, `fi ...[truncated 1475 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Do not cache authorization decisions unless cache equivalence can be proven. - Prefer disabling decision caching for actions that write, delete, execute code, send messages, or create payments. - If caching is retained, derive the key from a canonical serialization of every policy-relevant field: - normalized action type; - complete action data; - complete context; - agent identity; - policy file and policy-pack version; - governance mode and tenant identity. - Hash the canonical representation to avoid oversized dictionary keys. - Clear the cache whenever policies or policy packs change. - Consider limiting caching to explicit policies marked as safe to cache. - Add regression tests in which a benign `file.write` is followed by `email.delete`, `file.delete`, and `calendar.delete`. - Add an equivalent test in which an ordinary API call is followed by `payment.create`. ]]>
