Files
openclaw/src/security/dangerous-tools.ts
Omar Shahine 364d8be010 feat(agents): rename scheduler agent tool cron -> automations (#114841)
* refactor(agents): route scheduler tool-name consumers through canonical identity

Introduce AUTOMATIONS_TOOL_NAME + isAutomationsToolName() in
src/agents/tools/automations-tool-name.ts as the single source of truth for
the scheduler agent tool's name, and convert every exact-name consumer:
factory descriptors, deferred-followup availability detection, add-counting,
policy deny lists, mutation classification, trusted media set, tool catalog
id, system-prompt tool order and tool-line map, sandbox deny defaults,
delegation capability map, MCP loopback probes, and local-model lean deny.

Behavior-neutral: the constant still resolves to "cron". Prepares the
rename in RFC openclaw/rfcs#50 so the flip is a one-line change with no
scattered literals.

* feat(agents): rename scheduler agent tool cron -> automations

Flip AUTOMATIONS_TOOL_NAME to "automations" and register the legacy name:

- TOOL_NAME_ALIASES gains cron -> automations, so persisted toolsAllow/
  toolsDeny lists, tool groups, and creator allowlists written before the
  rename keep matching through the same shipped mechanism as bash -> exec.
  No doctor rewrite needed.
- isAutomationsToolName() accepts legacy names so saved transcripts keep
  their mutation/replay-safety classification; MUTATING_TOOL_NAMES retains
  the legacy entry for the same reason.
- Tool label, catalog label, and tool-search keywords follow the rename
  ("cron" kept as a search synonym).
- Regression tests cover old-name policy matching (allow and deny), legacy
  transcript replay classification, and legacy creator allowlists
  normalizing to the canonical id.

Model-facing description strings still say cron; those move in the
follow-up strings PR. Part of RFC openclaw/rfcs#50 Phase 1.

* test(agents): update creator-cap expectations for canonical automations id

The creator tool surface derives from normalized live tool names, so derived
toolsAllow outputs now emit "automations". Passthrough paths without a
creator cap keep storing user input verbatim; those expectations stay on the
legacy name as stored-data coverage.

* fix(gateway): canonicalize legacy cron tool calls and restore scheduler deny protection

Review follow-ups from ClawSweeper and Codex on the rename (RFC 0026):

- MCP loopback tools/call resolves legacy "cron" names to the published
  automations tool without re-advertising the old name in tools/list.
- Gateway /tools/invoke canonicalizes legacy names before core-id checks and
  exact-name dispatch, so pre-rename integrations keep working.
- Security fix: dangerous-tools deny lists (owner-only HTTP deny and
  control-plane set) were keyed on the literal "cron", so the renamed tool
  silently lost default-deny and owner-only protection on the HTTP invoke
  surface. Lists now use the canonical constant, and the gateway.tools.allow
  un-deny filter normalizes both sides so legacy allow entries still lift it.
- Voice high-impact confirmation list and MCP serve creator allowlist follow
  the canonical name.

Existing cron-regression suite now proves the legacy path end to end:
default deny 404 for both names, legacy allow entry lifts the deny, and
non-owner protection holds.

* fix(agents): cover stdio MCP legacy calls, probe prompts, and prompt snapshots for the rename

- stdio MCP servers (openclaw-tools-serve / plugin tools handlers) resolve
  legacy "cron" callTool names to the published canonical tool, matching
  the HTTP loopback behavior; listTools stays canonical-only.
- Live probe prompts instruct harnesses to load/call the automations MCP
  tool (mcp__openclaw__automations) instead of the retired name.
- Prompt snapshot fixture filter follows the canonical name (the renamed
  tool had silently dropped out of the Codex dynamic-tools snapshots);
  snapshots regenerated as a clean rename.
- Type-cast the new mcp-http handler test payloads for check-test-types.

* test(agents): update tool-surface expectations for the automations rename

CI-surfaced fallout in shards not covered by the focused local runs: tool
availability, agent-config filtering, coding-tools construction,
model-provider lean policy, and skill dispatch all assert the scheduler
tool's surface name. Mock fixtures and expectations follow the canonical
id; legacy-name coverage stays in the dedicated policy/creator-cap/invoke
regression suites.

* test(gateway): update tool-resolution exclude expectations for automations rename

* test(security): update trust-model audit expectations for automations rename

* docs(agents): declare cron a permanent scheduler-tool alias per owner decision

Maintainer decision (Omar): cron is not being retired anywhere — config keys,
RPC methods, schedule syntax, and the CLI token all keep it, and the tool
alias follows the same permanent contract as bash -> exec. No doctor rewrite
and no removal window; comments updated to state the contract instead of a
deprecation plan.

* chore(agents): regen prompt snapshots after rebase onto main

* fix(agents): teach canonical automations tool in fallback guidance and reuse the identity source

Review follow-ups: the structured-list fallback still taught models the cron
tool; the cron-scope test echoed its own stub; MCP serve allowlist and voice
confirmation hardcoded the name instead of the canonical constant.

* fix(mcp): place automations identity import outside the header comment

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-07-30 07:16:13 -07:00

72 lines
2.5 KiB
TypeScript

// Shared tool-risk constants.
// Keep these centralized so gateway HTTP restrictions and security audits don't drift.
import { AUTOMATIONS_TOOL_NAME } from "../agents/tools/automations-tool-name.js";
/**
* Tools denied via Gateway HTTP `POST /tools/invoke` by default.
* These are high-risk because they enable session orchestration, control-plane actions,
* or interactive flows that don't make sense over a non-interactive HTTP surface.
*/
export const DEFAULT_GATEWAY_HTTP_TOOL_DENY = [
// Direct command execution — immediate RCE surface
"exec",
// Arbitrary child process creation — immediate RCE surface
"spawn",
// Shell command execution — immediate RCE surface
"shell",
// Arbitrary file mutation on the host
"fs_write",
// Arbitrary file deletion on the host
"fs_delete",
// Arbitrary file move/rename on the host
"fs_move",
// Patch application can rewrite arbitrary files
"apply_patch",
// Agent-owned host terminal — interactive RCE surface
"terminal",
// Session orchestration — spawning agents remotely is RCE
"sessions_spawn",
// Cross-session injection — message injection across sessions
"sessions_send",
// External conversation discovery and delivery use server-held channel credentials
"conversations_list",
"conversations_send",
"conversations_turn",
// Persistent automation control plane — can create/update/remove scheduled runs
AUTOMATIONS_TOOL_NAME,
// Gateway config can expose secrets and host topology
"gateway",
// Node command relay can reach system.run on paired hosts
"nodes",
// Desktop control on a paired Mac (pointer/keyboard) and screen reads
"computer",
// Android AccessibilityService reads and cross-app UI control
"mobile_ui",
"openclaw",
] as const;
/**
* Sensitive control-plane tools. `automations` can persist scheduled runs; `gateway`
* exposes configuration and schema details even though its agent actions are read-only.
*/
export const GATEWAY_CONTROL_PLANE_TOOLS = [AUTOMATIONS_TOOL_NAME, "gateway"] as const;
/**
* Core tools that require sender owner identity on Gateway-scoped surfaces.
* `gateway.tools.allow` can remove the default HTTP deny only for owner/trusted-operator
* callers; non-owner identity-bearing callers must not receive server-credential wrappers.
*/
export const GATEWAY_OWNER_ONLY_CORE_TOOLS = [
...GATEWAY_CONTROL_PLANE_TOOLS,
"sessions",
"screen",
"terminal",
"conversations_list",
"conversations_send",
"conversations_turn",
"nodes",
"computer",
"mobile_ui",
"openclaw",
] as const;