Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 47 additions & 22 deletions integrations/openclaw/openclaw_gateway_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ def normalize_env() -> Dict[str, str]:
re.compile(r"curl\s+.+\|\s*sh"),
]

TOOL_METHOD_MAP = {
"run_terminal_cmd": "exec",
"terminal": "exec",
"read_file": "read",
"file_read": "read",
"write_file": "write",
"file_write": "write",
"process_state": "process",
"workflow_state": "process",
}


@dataclass
class ApprovalResult:
Expand Down Expand Up @@ -116,14 +127,27 @@ def __init__(self) -> None:

@staticmethod
def _map_method(neurorift_tool_call: Dict[str, Any]) -> str:
call_type = neurorift_tool_call.get("type")
if call_type == "run_terminal_cmd":
return "exec"
if call_type == "read_file":
return "read"
if call_type == "write_file":
return "write"
return "process"
call_type = neurorift_tool_call.get("type", "")
return TOOL_METHOD_MAP.get(call_type, "process")
Comment on lines +130 to +131
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle non-string tool types before method lookup

_map_method now does TOOL_METHOD_MAP.get(call_type, "process"), which raises TypeError when type is a dict/list (possible with variant or malformed websocket payloads). The previous equality-chain safely fell back to process; this change can now crash _build_rpc_frame and terminate the adapter loop on a single bad event.

Useful? React with 👍 / 👎.


@staticmethod
def _extract_command_preview(tool_call: Dict[str, Any], rpc_method: str) -> str:
if rpc_method != "exec":
return ""

for key in ("command", "cmd", "shell", "input"):
value = tool_call.get(key)
if isinstance(value, str) and value.strip():
return value
Comment on lines +138 to +141
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prefer payload command over input for risk approval

For exec calls that include both a descriptive input string and the real shell command under payload.command, _extract_command_preview returns input first, so high-risk checks can miss dangerous commands (e.g. rm -rf ...) and incorrectly auto-approve execution. This regression is specific to mixed-shape payloads and weakens the approval gate compared with scanning the full tool-call JSON.

Useful? React with 👍 / 👎.


payload = tool_call.get("payload")
if isinstance(payload, dict):
for key in ("command", "cmd"):
value = payload.get(key)
if isinstance(value, str) and value.strip():
return value

return json.dumps(tool_call, ensure_ascii=False)

async def _call_neurorift(self, payload: Dict[str, Any]) -> Dict[str, Any]:
async with httpx.AsyncClient(timeout=self.request_timeout) as client:
Expand All @@ -133,21 +157,22 @@ async def _call_neurorift(self, payload: Dict[str, Any]) -> Dict[str, Any]:

async def _build_rpc_frame(self, tool_call: Dict[str, Any]) -> Dict[str, Any]:
rpc_method = self._map_method(tool_call)
command_preview = json.dumps(tool_call, ensure_ascii=False)
command_preview = self._extract_command_preview(tool_call, rpc_method)

approval = await self.approval_forwarder.evaluate(
command_preview, self.session_id
)
if not approval.approved:
return {
"type": "rpc.reject",
"id": str(uuid.uuid4()),
"session": {"id": self.session_id, "mode": "isolated"},
"error": {
"code": "approval_required",
"message": approval.reason,
},
}
if rpc_method == "exec":
approval = await self.approval_forwarder.evaluate(
command_preview, self.session_id
)
if not approval.approved:
return {
"type": "rpc.reject",
"id": str(uuid.uuid4()),
"session": {"id": self.session_id, "mode": "isolated"},
"error": {
"code": "approval_required",
"message": approval.reason,
},
}

bridged = await self._call_neurorift(tool_call)

Expand Down
Loading