- Remove unused `sessionmaker` import from test_nl2sql_security.py
- Use `Self` return type on `_apply_env_override` (fixes UP037/F821)
- Fix ruff errors auto-fixed in lib/crewai (UP007, etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: remove CodeInterpreterTool and deprecate code execution params
CodeInterpreterTool has been removed. The allow_code_execution and
code_execution_mode parameters on Agent are deprecated and will be
removed in v2.0. Use dedicated sandbox services (E2B, Modal, etc.)
for code execution needs.
Changes:
- Remove CodeInterpreterTool from crewai-tools (tool, Dockerfile, tests, imports)
- Remove docker dependency from crewai-tools
- Deprecate allow_code_execution and code_execution_mode on Agent
- get_code_execution_tools() returns empty list with deprecation warning
- _validate_docker_installation() is a no-op with deprecation warning
- Bedrock CodeInterpreter (AWS hosted) and OpenAI code_interpreter are NOT affected
* fix: remove empty code_interpreter imports and unused stdlib imports
- Remove empty `from code_interpreter_tool import ()` blocks in both
crewai_tools/__init__.py and tools/__init__.py that caused SyntaxError
after CodeInterpreterTool was removed
- Remove unused `shutil` and `subprocess` imports from agent/core.py
left over from the code execution params deprecation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: remove redundant _validate_docker_installation call and fix list type annotation
- Drop the _validate_docker_installation() call inside the allow_code_execution
block — it fired a second DeprecationWarning identical to the one emitted
just above it, making the warning fire twice.
- Annotate get_code_execution_tools() return type as list[Any] to satisfy mypy
(bare `list` fails the type-arg check introduced by this branch).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: retrigger
* fix: update test_crew.py to remove CodeInterpreterTool references
CodeInterpreterTool was removed from crewai_tools. Update tests to
reflect that get_code_execution_tools() now returns an empty list.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update tool specifications
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
- Pass RuntimeState through the event bus and enable entity auto-registration
- Introduce checkpointing API:
- .checkpoint(), .from_checkpoint(), and async checkpoint support
- Provider-based storage with BaseProvider and JsonProvider
- Mid-task resume and kickoff() integration
- Add EventRecord tracking and full event serialization with subtype preservation
- Enable checkpoint fidelity via llm_type and executor_type discriminators
- Refactor executor architecture:
- Convert executors, tools, prompts, and TokenProcess to BaseModel
- Introduce proper base classes with typed fields (CrewAgentExecutorMixin, BaseAgentExecutor)
- Add generic from_checkpoint with full LLM serialization
- Support executor back-references and resume-safe initialization
- Refactor runtime state system:
- Move RuntimeState into state/ module with async checkpoint support
- Add entity serialization improvements and JSON-safe round-tripping
- Implement event scope tracking and replay for accurate resume behavior
- Improve tool and schema handling:
- Make BaseTool fully serializable with JSON round-trip support
- Serialize args_schema via JSON schema and dynamically reconstruct models
- Add automatic subclass restoration via tool_type discriminator
- Enhance Flow checkpointing:
- Support restoring execution state and subclass-aware deserialization
- Performance improvements:
- Cache handler signature inspection
- Optimize event emission and metadata preparation
- General cleanup:
- Remove dead checkpoint payload structures
- Simplify entity registration and serialization logic
* chore: update uv.lock with new dependency groups and versioning adjustments
- Added a new revision number and updated resolution markers for Python version compatibility.
- Introduced a 'dev' dependency group with specific versions for various development tools.
- Updated sdist and wheels entries to include upload timestamps for better tracking.
- Adjusted numpy dependencies to specify versions based on Python version markers.
* feat: bump versions to 1.14.0a1
* fix: add base_dir path containment to FileWriterTool
os.path.join does not prevent traversal — joining "./" with "../../../etc/cron.d/pwned"
resolves cleanly outside any intended scope. The tool also called os.makedirs on
the unvalidated path, meaning it would create arbitrary directory structures.
Adds a base_dir parameter that uses os.path.realpath() to resolve the final path
(including symlinks) before checking containment. Any filename or directory argument
that resolves outside base_dir is rejected before any filesystem operation occurs.
When base_dir is not set the tool behaves as before — only use that in fully
sandboxed environments.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: make directory relative to base_dir for better UX
When base_dir is set, the directory arg is now treated as a subdirectory
of base_dir rather than an absolute path. This means the LLM only needs
to specify a filename (and optionally a relative subdirectory) — it does
not need to repeat the base_dir path.
FileWriterTool(base_dir="./output")
→ filename="report.txt" writes to ./output/report.txt
→ filename="f.txt", directory="sub" writes to ./output/sub/f.txt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: remove directory field from LLM schema when base_dir is set
When a developer sets base_dir, they control where files are written.
The LLM should only supply filename and content — not a directory path.
Adds ScopedFileWriterToolInput (no directory field) which is used when
base_dir is provided at construction, following the same pattern as
FileReadTool/ScrapeWebsiteTool.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: prevent path traversal in FileWriterTool without interface changes
Adds containment check inside _run() using os.path.realpath() to ensure
the resolved file path stays within the resolved directory. Blocks ../
sequences, absolute filenames, and symlink escapes transparently —
no schema or interface changes required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: use Path.is_relative_to() for path containment check
Replaces startswith(real_directory + os.sep) with Path.is_relative_to(),
which does a proper path-component comparison. This avoids the edge case
where real_directory == "/" produces a "//" prefix, and is safe on
case-insensitive filesystems. Also explicitly rejects the case where
the filepath resolves to the directory itself (not a valid file target).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: fix portability issues in path traversal tests
- test_blocks_traversal_in_filename: use a sibling temp dir instead of
asserting against a potentially pre-existing ../outside.txt
- test_blocks_absolute_path_in_filename: use a temp-dir-derived absolute
path instead of hardcoding /etc/passwd
- test_blocks_symlink_escape: symlink to a temp "outside" dir instead of
/etc, assert target file was not created
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Greyson LaLonde <greyson.r.lalonde@gmail.com>
* fix: replace os.system with subprocess.run in unsafe mode pip install
Eliminates shell injection risk (A05) where a malicious library name like
"pkg; rm -rf /" could execute arbitrary host commands. Using list-form
subprocess.run with shell=False ensures the library name is always treated
as a single argument with no shell metacharacter expansion.
Adds two tests: one verifying list-form invocation, one verifying that
shell metacharacters in a library name cannot trigger shell execution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: use sys.executable -m pip to satisfy S607 linting rule
S607 flags partial executable paths like ["pip", ...]. Using
[sys.executable, "-m", "pip", ...] provides an absolute path and also
ensures installation targets the correct Python environment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Greyson LaLonde <greyson.r.lalonde@gmail.com>
* [SECURITY] Fix sandbox escape vulnerability in CodeInterpreterTool (F-001)
This commit addresses a critical security vulnerability where the CodeInterpreterTool
could be exploited via sandbox escape attacks when Docker was unavailable.
Changes:
- Remove insecure fallback to restricted sandbox in run_code_safety()
- Now fails closed with RuntimeError when Docker is unavailable
- Mark run_code_in_restricted_sandbox() as deprecated and insecure
- Add clear security warnings to SandboxPython class documentation
- Update tests to reflect secure-by-default behavior
- Add test demonstrating the sandbox escape vulnerability
- Update README with security requirements and best practices
The previous implementation would fall back to a Python-based 'restricted sandbox'
when Docker was unavailable. However, this sandbox could be easily bypassed using
Python object introspection to recover the original __import__ function, allowing
arbitrary module access and command execution on the host.
The fix enforces Docker as a requirement for safe code execution. Users who cannot
use Docker must explicitly enable unsafe_mode=True, acknowledging the security risks.
Security Impact:
- Prevents RCE via sandbox escape when Docker is unavailable
- Enforces fail-closed security model
- Maintains backward compatibility via unsafe_mode flag
References:
- https://docs.crewai.com/tools/ai-ml/codeinterpretertool
Co-authored-by: Rip&Tear <theCyberTech@users.noreply.github.com>
* Add security fix documentation for F-001
Co-authored-by: Rip&Tear <theCyberTech@users.noreply.github.com>
* Add Slack summary for security fix
Co-authored-by: Rip&Tear <theCyberTech@users.noreply.github.com>
* Delete SECURITY_FIX_F001.md
* Delete SLACK_SUMMARY.md
* chore: regen cassettes
* chore: regen more cassettes
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Rip&Tear <theCyberTech@users.noreply.github.com>
Co-authored-by: Greyson LaLonde <greyson@crewai.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: remove exclusive locks from read-only storage operations to eliminate lock contention
read operations like search, list_scopes, get_scope_info, count across
LanceDB, ChromaDB, and RAG adapters were holding exclusive locks unnecessarily.
under multi-process prefork workers this caused RedisLock contention triggering
a portalocker bug where AlreadyLocked is raised with the exceptions module as its arg.
- remove store_lock from 7 LanceDB read methods since MVCC handles concurrent reads
- remove store_lock from ChromaDB search/asearch which are thread-safe since v0.4
- remove store_lock from RAG core query and LanceDB adapter query
- wrap lock_store BaseLockException with actionable error message
- add exception handling in encoding_flow/recall_flow ThreadPoolExecutor calls
- fix flow.py double-logging of ancestor listener errors
* fix: remove dead conditional in filter_and_chunk fallback
both branches of the if/else and the except all produced the same
candidates = [scope_prefix] result, making the get_scope_info call
and conditional pointless
* fix: separate lock acquisition from caller body in lock_store
the try/except wrapped the yield inside the contextmanager, which meant
any BaseLockException raised by the caller's code inside the with block
would be caught and re-raised with a misleading "Failed to acquire lock"
message. split into acquire-then-yield so only actual acquisition
failures get the actionable error message.
* feat: add dedicated Brave Search tools for web, news, image, video, local POIs, and Brave's newest LLM Context endpoint
* fix: normalize transformed response shape
* revert legacy tool name
* fix: schema change prevented property resolution
* Update tool.specs.json
* fix: add fallback for search_langugage
* simplify exports
* makes rate-limiting logic per-instance
* fix(brave-tools): correct _refine_response return type annotations
The abstract method and subclasses annotated _refine_response as returning
dict[str, Any] but most implementations actually return list[dict[str, Any]].
Updated base to return Any, and each subclass to match its actual return type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Joao Moura <joaomdmoura@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: update step callback methods to support asynchronous invocation
- Replaced synchronous step callback invocations with asynchronous counterparts in the CrewAgentExecutor class.
- Introduced a new async method _ainvoke_step_callback to handle step callbacks in an async context, improving responsiveness and performance in asynchronous workflows.
* chore: bump version to 1.10.1b1 across multiple files
- Updated version strings from 1.10.1b to 1.10.1b1 in various project files including pyproject.toml and __init__.py files.
- Adjusted dependency specifications to reflect the new version in relevant templates and modules.