crewai - โœ…(Solved) Fix Enforce fail-closed defaults for unsafe tool execution [2 pull requests, 2 comments, 2 participants]

Official PRs (โ€ฆ)
ON THIS PAGE

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
crewAIInc/crewAI#4593โ€ขFetched 2026-04-08 00:41:07
View on GitHub
Comments
2
Participants
2
Timeline
10
Reactions
0
Timeline (top)
cross-referenced ร—3referenced ร—3commented ร—2closed ร—1

Error Message

  • Deterministic error classification and messaging.

Fix Action

Fixed

PR fix notes

PR #4594: feat: enforce fail-closed defaults for unsafe tool execution

Description (problem / solution / changelog)

feat: enforce fail-closed defaults for unsafe tool execution

Summary

Fixes #4593 โ€” Adds an unsafe: bool flag to tools and enforces fail-closed behavior: tools marked unsafe=True are denied by default unless a before_tool_call hook explicitly returns True.

Changes:

  • BaseTool: new unsafe: bool = False field, propagated to CrewStructuredTool via to_structured_tool()
  • @tool decorator: new unsafe keyword argument
  • CrewStructuredTool.__init__: accepts and stores unsafe parameter
  • Fail-closed enforcement added to all 4 tool execution paths:
    • crew_agent_executor.py (native tool calling)
    • experimental/agent_executor.py (experimental executor)
    • tool_utils.py sync + async (ReAct text-based path)
  • 15 regression tests covering allow/deny paths

Hook semantics:

Hook returnEffect on safe toolEffect on unsafe tool
TrueAllowedAllowed (explicit approval)
NoneAllowedDenied (neutral โ‰  approval)
FalseBlockedBlocked
No hooksAllowedDenied

Updates since last revision

  • Removed unused imports (Mock, get_before_tool_call_hooks, unregister_before_tool_call_hook) from test file per code-quality bot feedback.

Review & Testing Checklist for Human

  • Verify the 4 enforcement sites are consistent: The same logic is duplicated in crew_agent_executor.py, experimental/agent_executor.py, tool_utils.py (sync), and tool_utils.py (async). Confirm behavior matches across all 4. Note: tool_utils.py uses if/if with early returns while the executors use if/elif โ€” functionally equivalent but stylistically different.
  • Test with a real Crew/Agent: The tests only cover the execute_tool_and_check_finality path (ReAct text-based). The native tool calling paths (crew_agent_executor, experimental/agent_executor) are not directly tested. Manually verify with a Crew that uses native function calling (e.g., OpenAI tools) that unsafe tools are properly blocked/allowed.
  • Edge case: hook returns False on an unsafe tool: When a hook explicitly returns False on an unsafe tool, the error message shown is the unsafe-specific "fail-closed" message rather than the generic "blocked by hook" message. Verify this is the desired UX โ€” a user who registered a blocking hook might expect the generic blocked message instead.
  • Verify ValidationError removal: ValidationError import was removed from base_tool.py โ€” confirm it's truly unused (ruff likely auto-removed it).

Recommended Test Plan

  1. Create a tool marked unsafe=True using the @tool decorator
  2. Test with a Crew using native function calling (e.g., OpenAI model with tools):
    • Without any hooks โ†’ should be denied with fail-closed message
    • With a hook returning None โ†’ should be denied
    • With a hook returning True โ†’ should execute successfully
    • With a hook returning False โ†’ should be blocked
  3. Verify safe tools (default unsafe=False) are unaffected

Notes

Changed files

  • lib/crewai/src/crewai/agents/crew_agent_executor.py (modified, +22/-1)
  • lib/crewai/src/crewai/experimental/agent_executor.py (modified, +22/-1)
  • lib/crewai/src/crewai/tools/base_tool.py (modified, +16/-1)
  • lib/crewai/src/crewai/tools/structured_tool.py (modified, +4/-0)
  • lib/crewai/src/crewai/utilities/tool_utils.py (modified, +56/-10)
  • lib/crewai/tests/hooks/test_unsafe_tool_fail_closed.py (added, +349/-0)

PR #4596: Fail closed on unsafe code execution without explicit policy and pre-execution confirmation

Description (problem / solution / changelog)

Problem

Unsafe code execution can be routed into crew task execution without strict, pre-execution confirmation guarantees, creating permissive high-risk tool behavior.

Why now

Issue #4593 asks for fail-closed unsafe tool execution defaults as crew autonomy scales and safety boundaries must be explicit.

What changed

  • Added explicit agent policy flag: allow_unsafe_code_execution (default False).
  • Added explicit pre-execution confirmation gate: unsafe_code_execution_confirmation callable.
  • Added fail-closed guard in crew tool preparation for unsafe code execution mode.
  • Unsafe mode now errors unless:
    • allow_unsafe_code_execution=True, and
    • unsafe_code_execution_confirmation is callable and returns True before tool injection.
  • Added tests for missing allow policy, missing confirmation gate, negative confirmation result, and allowed path.

Validation

  • uv run ruff format lib/crewai/src/crewai/agent/core.py lib/crewai/src/crewai/crew.py lib/crewai/src/crewai/project/crew_base.py lib/crewai/tests/test_crew.py (pass)
  • uv run ruff check lib/crewai/src/crewai/agent/core.py lib/crewai/src/crewai/crew.py lib/crewai/src/crewai/project/crew_base.py lib/crewai/tests/test_crew.py (pass)
  • uv run pytest lib/crewai/tests/test_crew.py -k 'code_execution_flag_adds_code_tool_upon_kickoff or unsafe_code_execution_requires_explicit_allow_policy or unsafe_code_execution_requires_confirmation_setting or unsafe_code_execution_requires_positive_confirmation or unsafe_code_execution_allowed_with_policy_and_confirmation_gate' (pass)

Refs #4593

Changed files

  • lib/crewai/src/crewai/agent/core.py (modified, +11/-0)
  • lib/crewai/src/crewai/crew.py (modified, +35/-3)
  • lib/crewai/src/crewai/project/crew_base.py (modified, +2/-0)
  • lib/crewai/tests/test_crew.py (modified, +107/-0)
RAW_BUFFERClick to expand / collapse

Problem

Unsafe tool execution can proceed under permissive defaults when safety configuration is incomplete, increasing blast radius in autonomous crew execution.

Why now

CrewAI adoption in multi-agent automation makes strict default safety posture more important for predictable operations.

Evidence Packet

  • Version/commit under test: origin/main at 8102d0a6cade
  • Runtime environment: macOS 26.3 (arm64), Python 3.14.0
  • Minimal repro:
    1. Configure crew with unsafe/high-impact tool.
    2. Leave safety policy/confirmation config incomplete.
    3. Execute crew run path.
  • Expected behavior: fail-closed block until explicit allow/confirmation policy is set.
  • Actual behavior: safety defaults are not uniformly strict at tool execution boundaries.

Why code change (not docs)

Runtime safety policy must be enforced in execution codepaths.

Scope / Codepaths

  • lib/crewai/src/crewai/tools
  • lib/crewai/src/crewai/security
  • lib/crewai/src/crewai/crews

Acceptance Criteria

  • Unsafe tools denied by default without explicit policy.
  • Deterministic error classification and messaging.
  • Regression tests for allow/deny paths.

Validation Plan

  • Add targeted unit tests for incomplete safety config.
  • Verify fail-closed behavior in crew execution path.

extent analysis

Fix Plan

To address the issue, we will implement a strict default safety posture by enforcing runtime safety policy in execution codepaths. The fix involves modifying the crewai code to deny unsafe tools by default without an explicit policy.

Steps:

  • Update lib/crewai/src/crewai/tools to include a default deny policy for unsafe tools.
  • Modify lib/crewai/src/crewai/security to enforce the safety policy at tool execution boundaries.
  • Change lib/crewai/src/crewai/crews to fail-closed when safety configuration is incomplete.

Example Code:

# lib/crewai/src/crewai/tools.py
def execute_tool(tool):
    if not is_safe_tool(tool) and not has_explicit_policy():
        raise SafetyPolicyError("Unsafe tool execution denied by default")

# lib/crewai/src/crewai/security.py
def enforce_safety_policy(tool):
    if not has_explicit_policy():
        return False
    # existing policy enforcement logic

# lib/crewai/src/crewai/crews.py
def run_crew(crew):
    if not has_complete_safety_config():
        raise SafetyConfigError("Incomplete safety configuration")
    # existing crew execution logic

Verification

To verify the fix, add targeted unit tests for incomplete safety config and test the fail-closed behavior in the crew execution path.

Extra Tips

  • Ensure regression tests cover both allow and deny paths.
  • Review existing codepaths for similar safety policy enforcement opportunities.

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

crewai - โœ…(Solved) Fix Enforce fail-closed defaults for unsafe tool execution [2 pull requests, 2 comments, 2 participants]