diff --git a/.github/workflows/vulnerability-scan.yml b/.github/workflows/vulnerability-scan.yml index e137e702d..31c270f42 100644 --- a/.github/workflows/vulnerability-scan.yml +++ b/.github/workflows/vulnerability-scan.yml @@ -47,52 +47,20 @@ jobs: - name: Run pip-audit run: | - uv run pip-audit --desc --aliases --skip-editable --format json --output pip-audit-report.json \ - --ignore-vuln PYSEC-2024-277 \ - --ignore-vuln PYSEC-2026-89 \ - --ignore-vuln PYSEC-2026-97 \ - --ignore-vuln PYSEC-2025-148 \ - --ignore-vuln PYSEC-2025-183 \ - --ignore-vuln PYSEC-2025-189 \ - --ignore-vuln PYSEC-2025-190 \ - --ignore-vuln PYSEC-2025-191 \ - --ignore-vuln PYSEC-2025-192 \ - --ignore-vuln PYSEC-2025-193 \ - --ignore-vuln PYSEC-2025-194 \ - --ignore-vuln PYSEC-2025-195 \ - --ignore-vuln PYSEC-2025-196 \ - --ignore-vuln PYSEC-2025-197 \ - --ignore-vuln PYSEC-2025-210 \ - --ignore-vuln PYSEC-2026-139 \ - --ignore-vuln GHSA-rrmf-rvhw-rf47 \ - --ignore-vuln PYSEC-2025-211 \ - --ignore-vuln PYSEC-2025-212 \ - --ignore-vuln PYSEC-2025-213 \ - --ignore-vuln PYSEC-2025-214 \ - --ignore-vuln PYSEC-2025-215 \ - --ignore-vuln PYSEC-2025-216 \ - --ignore-vuln PYSEC-2025-217 \ - --ignore-vuln PYSEC-2025-218 \ - --ignore-vuln PYSEC-2026-597 \ - --ignore-vuln GHSA-f4j7-r4q5-qw2c \ - --ignore-vuln GHSA-xf7x-x43h-rpqh - # Ignored CVEs: - # PYSEC-2024-277 - joblib 1.5.3: disputed; NumpyArrayWrapper only used with trusted caches - # PYSEC-2026-89 - markdown 3.10.2: DoS via malformed HTML; fix 3.8.1 — already past, advisory range is stale - # PYSEC-2026-97 - nltk 3.9.4: arbitrary file read in filestring(); no fix available - # PYSEC-2026-597 - nltk 3.9.4 (CVE-2026-12243): path traversal via _UNSAFE_NO_PROTOCOL_RE bypass (incomplete fix of nltk#3504); 3.9.4 is the latest release, no fix available - # PYSEC-2025-148 - onnx 1.21.0: path traversal in save_external_data; no fix available - # PYSEC-2025-183 - pyjwt 2.12.1: disputed weak-encryption claim; key length is application-chosen - # PYSEC-2025-189..197 - torch 2.11.0: memory-corruption/DoS in functions only reachable via untrusted models; no fix available - # PYSEC-2025-210, PYSEC-2026-139 - torch 2.11.0: profiler/deserialization issues; no fix available - # GHSA-rrmf-rvhw-rf47 - torch 2.11.0 (CVE-2025-3000, alias of PYSEC-2025-194): memory corruption in torch.jit.script, CVSS 1.9, local-only; affected <=2.12.0, no fix available. pip-audit reports it under the GHSA id so the PYSEC ignore above does not catch it. - # PYSEC-2025-211..218 - transformers 5.5.4: deserialization/code injection via malicious model checkpoints; no fix available - # GHSA-f4j7-r4q5-qw2c - chromadb 1.1.1 (CVE-2026-45829): pre-auth RCE via /api/v2/tenants/{tenant}/databases/{db}/collections when trust_remote_code=true. - # Advisory: vulnerable >=1.0.0,<=1.5.9, firstPatchedVersion=none. We only use chromadb.PersistentClient (lib/crewai/src/crewai/rag/chromadb/factory.py) - # and chromadb.utils.embedding_functions; the chromadb HTTP server is never started, so the vulnerable route is not exposed. - # GHSA-xf7x-x43h-rpqh - json-repair 0.25.3 (published 2026-07-13): CPU DoS via circular $ref in SchemaRepairer.resolve_schema(). - # The vulnerable schema_repair module does not exist in 0.25.x (added in later releases), and CrewAI only calls - # repair_json() without schemas. The fixed release 0.60.1 is outside the json-repair~=0.25.2 pin. + pip_audit_args=( + --desc + --aliases + --skip-editable + --format json + --output pip-audit-report.json + --ignore-vuln CVE-2026-27448 # pyOpenSSL: fixes require 26.0.0, blocked by snowflake-connector-python 3.x. + --ignore-vuln CVE-2026-27459 # pyOpenSSL: same constraint as CVE-2026-27448. + --ignore-vuln PYSEC-2026-597 # nltk 3.9.4 (CVE-2026-12243): no fix available, transitive through crewai-tools[xml] -> unstructured. + --ignore-vuln GHSA-rrmf-rvhw-rf47 # torch 2.12.0 (CVE-2025-3000): local-only memory corruption in torch.jit.script; no fix available. + --ignore-vuln GHSA-f4j7-r4q5-qw2c # chromadb 1.1.1 (CVE-2026-45829): pre-auth RCE in the HTTP server; no fix available. + --ignore-vuln GHSA-xf7x-x43h-rpqh # json-repair 0.25.3: the affected schema module is absent, and CrewAI does not pass schemas. + ) + uv run pip-audit "${pip_audit_args[@]}" continue-on-error: true - name: Display results @@ -138,4 +106,3 @@ jobs: ~/.local/share/uv .venv key: uv-main-py3.11-${{ hashFiles('uv.lock') }} - diff --git a/lib/crewai-files/pyproject.toml b/lib/crewai-files/pyproject.toml index e4d6cd29e..398d94068 100644 --- a/lib/crewai-files/pyproject.toml +++ b/lib/crewai-files/pyproject.toml @@ -8,7 +8,7 @@ authors = [ ] requires-python = ">=3.10, <3.14" dependencies = [ - "Pillow~=12.1.1", + "Pillow~=12.3.0", "pypdf~=6.13.3", "python-magic>=0.4.27", "aiocache~=0.12.3", diff --git a/lib/crewai-tools/pyproject.toml b/lib/crewai-tools/pyproject.toml index b161421bf..d234b31dc 100644 --- a/lib/crewai-tools/pyproject.toml +++ b/lib/crewai-tools/pyproject.toml @@ -97,10 +97,10 @@ databricks-sdk = [ "databricks-sdk>=0.46.0", ] couchbase = [ - "couchbase>=4.3.5", + "couchbase>=4.6.0", ] mcp = [ - "mcp>=1.6.0", + "mcp>=1.28.1,<2", "mcpadapt>=0.1.9", ] stagehand = [ diff --git a/lib/crewai/pyproject.toml b/lib/crewai/pyproject.toml index aff43f2af..25a2549fa 100644 --- a/lib/crewai/pyproject.toml +++ b/lib/crewai/pyproject.toml @@ -40,7 +40,7 @@ dependencies = [ "portalocker~=2.7.0", "pydantic-settings>=2.10.1,<3", "httpx~=0.28.1", - "mcp~=1.26.0", + "mcp~=1.28.1", "aiosqlite~=0.21.0", "pyyaml~=6.0", "aiofiles~=24.1.0", diff --git a/lib/crewai/tests/agents/test_crew_agent_parser.py b/lib/crewai/tests/agents/test_crew_agent_parser.py index 2a975eed9..220ff7168 100644 --- a/lib/crewai/tests/agents/test_crew_agent_parser.py +++ b/lib/crewai/tests/agents/test_crew_agent_parser.py @@ -30,6 +30,14 @@ def test_valid_action_parsing_with_json_tool_input(): assert result.tool_input == expected_tool_input +def test_valid_action_parsing_preserves_markdown_like_plain_text(): + text = "Thought: Let's search\nAction: search\nAction Input: ** plain text" + result = parser.parse(text) + assert isinstance(result, AgentAction) + assert result.tool == "search" + assert result.tool_input == "** plain text" + + def test_valid_action_parsing_with_quotes(): text = 'Thought: Let\'s find the temperature\nAction: search\nAction Input: "temperature in SF"' result = parser.parse(text) diff --git a/pyproject.toml b/pyproject.toml index c242bc77f..e539c188a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -205,7 +205,7 @@ override-dependencies = [ "openai>=2.30.0,<3", "rich>=13.7.1", "onnxruntime<1.24; python_version < '3.11'", - "pillow>=12.1.1", + "pillow>=12.3.0", "langchain-core>=1.3.3,<2", "langchain-text-splitters>=1.1.2,<2", "urllib3>=2.7.0", diff --git a/uv.lock b/uv.lock index 5dfd6fb5c..e1b19a1df 100644 --- a/uv.lock +++ b/uv.lock @@ -44,7 +44,7 @@ overrides = [ { name = "onnxruntime", marker = "python_full_version < '3.11'", specifier = "<1.24" }, { name = "openai", specifier = ">=2.30.0,<3" }, { name = "paramiko", specifier = ">=5.0.0" }, - { name = "pillow", specifier = ">=12.1.1" }, + { name = "pillow", specifier = ">=12.3.0" }, { name = "pip", specifier = ">=26.1.2" }, { name = "pydantic-settings", specifier = ">=2.14.2" }, { name = "pypdf", specifier = ">=6.13.3,<7" }, @@ -1450,7 +1450,7 @@ requires-dist = [ { name = "jsonref", specifier = "~=1.1.0" }, { name = "lancedb", specifier = ">=0.29.2,<0.30.1" }, { name = "litellm", marker = "extra == 'litellm'", specifier = ">=1.84.0,<2" }, - { name = "mcp", specifier = "~=1.26.0" }, + { name = "mcp", specifier = "~=1.28.1" }, { name = "mem0ai", marker = "extra == 'mem0'", specifier = ">=2.0.0,<3" }, { name = "openai", specifier = ">=2.30.0,<3" }, { name = "openpyxl", specifier = "~=3.1.5" }, @@ -1593,7 +1593,7 @@ requires-dist = [ { name = "aiocache", specifier = "~=0.12.3" }, { name = "aiofiles", specifier = "~=24.1.0" }, { name = "av", specifier = "~=13.0.0" }, - { name = "pillow", specifier = "~=12.1.1" }, + { name = "pillow", specifier = "~=12.3.0" }, { name = "pypdf", specifier = "~=6.13.3" }, { name = "python-magic", specifier = ">=0.4.27" }, { name = "tinytag", specifier = "~=2.2.1" }, @@ -1745,7 +1745,7 @@ requires-dist = [ { name = "browserbase", marker = "extra == 'browserbase'", specifier = ">=1.0.5" }, { name = "composio-core", marker = "extra == 'composio-core'", specifier = ">=0.6.11.post1" }, { name = "contextual-client", marker = "extra == 'contextual'", specifier = ">=0.1.0" }, - { name = "couchbase", marker = "extra == 'couchbase'", specifier = ">=4.3.5" }, + { name = "couchbase", marker = "extra == 'couchbase'", specifier = ">=4.6.0" }, { name = "crewai", editable = "lib/crewai" }, { name = "cryptography", marker = "extra == 'snowflake'", specifier = ">=43.0.3" }, { name = "databricks-sdk", marker = "extra == 'databricks-sdk'", specifier = ">=0.46.0" }, @@ -1759,7 +1759,7 @@ requires-dist = [ { name = "langchain-apify", marker = "extra == 'apify'", specifier = ">=0.1.2,<1.0.0" }, { name = "linkup-sdk", marker = "extra == 'linkup-sdk'", specifier = ">=0.2.2" }, { name = "lxml", marker = "extra == 'rag'", specifier = ">=6.1.0,<7" }, - { name = "mcp", marker = "extra == 'mcp'", specifier = ">=1.6.0" }, + { name = "mcp", marker = "extra == 'mcp'", specifier = ">=1.28.1,<2" }, { name = "mcpadapt", marker = "extra == 'mcp'", specifier = ">=0.1.9" }, { name = "multion", marker = "extra == 'multion'", specifier = ">=1.1.0" }, { name = "nest-asyncio", marker = "extra == 'bedrock'", specifier = ">=1.6.0" }, @@ -4422,7 +4422,7 @@ wheels = [ [[package]] name = "mcp" -version = "1.26.0" +version = "1.28.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -4440,9 +4440,9 @@ dependencies = [ { name = "typing-inspection" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fc/6d/62e76bbb8144d6ed86e202b5edd8a4cb631e7c8130f3f4893c3f90262b10/mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66", size = 608005, upload-time = "2026-01-24T19:40:32.468Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/d9/eaa1f80170d2b7c5ba23f3b59f766f3a0bb41155fbc32a69adfa1adaaef9/mcp-1.26.0-py3-none-any.whl", hash = "sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca", size = 233615, upload-time = "2026-01-24T19:40:30.652Z" }, + { url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" }, ] [package.optional-dependencies]