openclaw - 💡(How to fix) Fix [Feature]: Tool security classification properties (isDestructive, isReadOnly, isConcurrencySafe) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#62962Fetched 2026-04-09 08:00:05
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0

Add six standard security classification properties to tool definitions so safety decisions (confirmation prompts, parallel scheduling, abort handling) are schema-driven rather than requiring per-call case analysis.

Error Message

/** Action is irreversible — always confirm; warn with "may" not "will". */

Root Cause

Add six standard security classification properties to tool definitions so safety decisions (confirmation prompts, parallel scheduling, abort handling) are schema-driven rather than requiring per-call case analysis.

Code Example

// src/agents/tools/common.ts — extend AnyAgentTool
export type AgentToolSecurityProps = {
  /** Does not modify any state — skip confirmation, allow unrestricted parallel use. */
  isReadOnly?: boolean;
  /** Action is irreversible — always confirm; warn with "may" not "will". */
  isDestructive?: boolean;
  /** Safe to run in parallel with other tool calls — no shared write dependency. */
  isConcurrencySafe?: boolean;
  /** On user interrupt: "cancel" kills immediately; "block" waits for clean finish. */
  interruptBehavior?: "cancel" | "block";
  /** Involves external systems (network, third-party APIs) — applies network policy. */
  isOpenWorld?: boolean;
  /** Compact one-line summary of the call for safety classifier input. */
  toAutoClassifierInput?: (args: unknown) => string;
};

---

export const webFetchTool = {
  name: "web_fetch",
  isReadOnly: true,
  isOpenWorld: true,
  isConcurrencySafe: true,
  interruptBehavior: "cancel",
  toAutoClassifierInput: (args) => `web_fetch ${(args as { url: string }).url}`,
};

export const execTool = {
  name: "exec",
  isReadOnly: false,
  isDestructive: false, // depends on command, but tool itself is not always destructive
  isConcurrencySafe: false,
  interruptBehavior: "block",
  isOpenWorld: true,
  toAutoClassifierInput: (args) => `exec ${(args as { command: string }).command?.slice(0, 80)}`,
};

export const fileDeleteTool = {
  name: "file_delete",
  isReadOnly: false,
  isDestructive: true,
  isConcurrencySafe: false,
  interruptBehavior: "block",
  isOpenWorld: false,
  toAutoClassifierInput: (args) => `file_delete ${(args as { path: string }).path}`,
};

---

// Permission layer: skip confirmation for read-only tools
if (tool.isReadOnly) return "allow";

// UI layer: extra confirmation + "may" warning for destructive tools
if (tool.isDestructive) {
  await confirm(`Note: may permanently affect ${tool.toAutoClassifierInput?.(args)}`);
}

// Parallel scheduler: run concurrently only when both tools declare safe
const canParallelize = toolA.isConcurrencySafe && toolB.isConcurrencySafe;
RAW_BUFFERClick to expand / collapse

Summary

Add six standard security classification properties to tool definitions so safety decisions (confirmation prompts, parallel scheduling, abort handling) are schema-driven rather than requiring per-call case analysis.

Problem to solve

Tool definitions currently carry ownerOnly and participate in allow/deny policy, but have no standard way to declare whether a tool is destructive, read-only, concurrency-safe, or involves external systems. This means:

  • Confirmation prompts are implemented ad-hoc per tool rather than driven by a declared isDestructive flag.
  • Parallel tool scheduling cannot be automated — the orchestrator has no schema signal for whether two tools can safely run simultaneously.
  • Abort behavior on user interrupt is inconsistent — some tools should cancel immediately, others should finish before stopping.
  • Safety classifiers lack a compact representation of what a tool call does, making per-call analysis expensive.

Scaffolding quality (including tool schema design) explains same-model score gaps of 17 issues on 731 SWE-bench problems (SWE-bench leaderboard, Feb 2026). Tool misuse is OWASP #5 agentic risk; tools without declared safety properties are the primary cause (OWASP Top 10 for Agentic Applications, 2026).

Proposed solution

1. Six classification properties

// src/agents/tools/common.ts — extend AnyAgentTool
export type AgentToolSecurityProps = {
  /** Does not modify any state — skip confirmation, allow unrestricted parallel use. */
  isReadOnly?: boolean;
  /** Action is irreversible — always confirm; warn with "may" not "will". */
  isDestructive?: boolean;
  /** Safe to run in parallel with other tool calls — no shared write dependency. */
  isConcurrencySafe?: boolean;
  /** On user interrupt: "cancel" kills immediately; "block" waits for clean finish. */
  interruptBehavior?: "cancel" | "block";
  /** Involves external systems (network, third-party APIs) — applies network policy. */
  isOpenWorld?: boolean;
  /** Compact one-line summary of the call for safety classifier input. */
  toAutoClassifierInput?: (args: unknown) => string;
};

2. Example annotations on existing tools

export const webFetchTool = {
  name: "web_fetch",
  isReadOnly: true,
  isOpenWorld: true,
  isConcurrencySafe: true,
  interruptBehavior: "cancel",
  toAutoClassifierInput: (args) => `web_fetch ${(args as { url: string }).url}`,
};

export const execTool = {
  name: "exec",
  isReadOnly: false,
  isDestructive: false, // depends on command, but tool itself is not always destructive
  isConcurrencySafe: false,
  interruptBehavior: "block",
  isOpenWorld: true,
  toAutoClassifierInput: (args) => `exec ${(args as { command: string }).command?.slice(0, 80)}`,
};

export const fileDeleteTool = {
  name: "file_delete",
  isReadOnly: false,
  isDestructive: true,
  isConcurrencySafe: false,
  interruptBehavior: "block",
  isOpenWorld: false,
  toAutoClassifierInput: (args) => `file_delete ${(args as { path: string }).path}`,
};

3. Drive safety decisions from schema

// Permission layer: skip confirmation for read-only tools
if (tool.isReadOnly) return "allow";

// UI layer: extra confirmation + "may" warning for destructive tools
if (tool.isDestructive) {
  await confirm(`Note: may permanently affect ${tool.toAutoClassifierInput?.(args)}`);
}

// Parallel scheduler: run concurrently only when both tools declare safe
const canParallelize = toolA.isConcurrencySafe && toolB.isConcurrencySafe;

4. Update conformance snapshot

Add the new properties to TOOL_POLICY_CONFORMANCE in src/agents/tool-policy.conformance.ts so CI detects drift when a tool is added without classification.

5. Warning language: "may" not "will"

Destructive operation warnings should use "may" not "will"git push --force does not overwrite anything if the remote hasn't diverged; rm -rf temp/ might be deleting disposable files. Overstated warnings cause alert fatigue; accurate warnings maintain credibility (BP 06).

Alternatives considered

  • Per-tool ad-hoc checks: current approach. Works but requires every new tool to re-implement the same safety logic, and misses tools that don't bother.
  • Allowlist-based safety: already in place via tool-policy.ts. Classification properties are the complement — they describe tool behavior, not access control.
  • Runtime classifier only: the toAutoClassifierInput property enables a separate lightweight safety query before execution (the critic/permission side-query pattern). This is a complement to, not a replacement for, schema-declared properties.

Impact

  • Affected: All tool definitions; parallel tool scheduling; confirmation prompt logic; safety classifier integration.
  • Severity: Medium — no current breakage, but the absence creates inconsistency and makes future safety automation harder.
  • Frequency: Every tool call in every session.
  • Consequence: Without declared properties, adding new safe-to-parallelize tools requires manual orchestrator changes; adding new destructive tools risks missing confirmation prompts.

Evidence/examples

  • OWASP Top 10 for Agentic Applications 2026: tool misuse (#5) — tools with poor descriptions/metadata are the primary cause.
  • SWE-bench leaderboard Feb 2026: scaffolding quality (including tool design) explains 17-issue gaps on same-model comparisons.
  • BP 04 (tool design): "every tool should declare six security properties as part of its definition — these properties drive automatic safety decisions without requiring per-call analysis."

Additional information

  • toAutoClassifierInput is the most subtle property: it compresses a tool invocation (including arguments) into a single line that a safety classifier can evaluate cheaply. Example: exec ls -la /project/src. The classifier sees that string and makes a binary safe/unsafe judgment without loading full tool context.
  • isDestructive = true should trigger: confirmation prompt, "may" (not "will") warning language, and a reversibility check (is there a safer alternative?).
  • Properties are optional — tools without them fall back to current behavior. Annotate high-risk tools first (exec, file_delete, git_push, web_fetch), then fill in the rest incrementally.
  • Related review: best-practices/results/agent-review-2026-04-07.md (dimension 04 — Tool design).

extent analysis

TL;DR

Add six standard security classification properties to tool definitions to drive safety decisions and improve consistency in confirmation prompts, parallel scheduling, and abort handling.

Guidance

  • Extend the AnyAgentTool type with the proposed AgentToolSecurityProps to include properties like isReadOnly, isDestructive, and isConcurrencySafe.
  • Annotate existing tools with these properties, as shown in the examples for webFetchTool, execTool, and fileDeleteTool.
  • Update the permission layer, UI layer, and parallel scheduler to drive safety decisions from the schema, using the new properties to determine confirmation prompts, parallelization, and abort behavior.
  • Incrementally annotate high-risk tools with the new properties, starting with tools like exec, file_delete, git_push, and web_fetch.

Example

export const webFetchTool = {
  name: "web_fetch",
  isReadOnly: true,
  isOpenWorld: true,
  isConcurrencySafe: true,
  interruptBehavior: "cancel",
  toAutoClassifierInput: (args) => `web_fetch ${(args as { url: string }).url}`,
};

Notes

The proposed solution requires updating existing tool definitions and the surrounding infrastructure to use the new security classification properties. This may involve significant changes to the codebase, but it should improve consistency and safety in the long run.

Recommendation

Apply the proposed workaround by adding the six standard security classification properties to tool definitions and updating the surrounding infrastructure to drive safety decisions from the schema. This should improve consistency and safety in the system.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING