fix: resolve high-severity Dependabot alerts and drop milvus-lite#393
Conversation
Bump Python constraints and lockfile for cryptography, PyJWT, urllib3, python-multipart, langsmith, langchain-classic, and docling. Add pnpm overrides for linkify-it and undici. setuptools and nltk remain risk- accepted with documented rationale (milvus-lite / no upstream fix).
📝 WalkthroughWalkthroughRemoves memory-related dependencies, configs, docs, and CLI references, updates the secrets baseline and frontend overrides, and changes assistant output handling so empty model content can fall back to reasoning or execution output while other text normalization paths accept dict content blocks. ChangesMemory Feature Removal & Dependency Hardening
Assistant Output Handling
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/cuga/cli/main.py`:
- Around line 858-862: The start() CLI help text is missing travel_agent even
though the command still accepts and dispatches it. Update the service Argument
help string in start() to include travel_agent alongside the other supported
services so --help matches the actual validation and dispatch behavior.
In `@src/frontend_workspaces/package.json`:
- Around line 66-68: Tighten the pnpm override for undici in the package
manifest so it stays compatible with the documented Node 18 support. Update the
undici entry in package.json to pin the fixed 7.28.0 release or otherwise cap it
below 8.x, and leave the linkify-it override as-is since it already targets the
patched version. Use the existing pnpm.overrides block to keep the transitive
resolution from pulling in the Node 22-only undici 8.x line.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d15df396-bf86-4bbe-966a-198eb7315904
⛔ Files ignored due to path filters (2)
src/frontend_workspaces/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamluv.lockis excluded by!**/*.lock
📒 Files selected for processing (17)
.secrets.baselineREADME.mddocs/memory/README.mdpyproject.tomlsrc/cuga/cli/main.pysrc/cuga/configurations/memory/memory_settings.mem0.tomlsrc/cuga/configurations/memory/memory_settings.milvus.tomlsrc/cuga/configurations/memory/memory_settings.tips_extractor.tomlsrc/cuga/configurations/models/settings.azure.tomlsrc/cuga/configurations/models/settings.google.tomlsrc/cuga/configurations/models/settings.groq.tomlsrc/cuga/configurations/models/settings.litellm.tomlsrc/cuga/configurations/models/settings.openai.tomlsrc/cuga/configurations/models/settings.openrouter.tomlsrc/cuga/configurations/models/settings.rits.tomlsrc/cuga/configurations/models/settings.watsonx.tomlsrc/frontend_workspaces/package.json
💤 Files with no reviewable changes (13)
- src/cuga/configurations/memory/memory_settings.tips_extractor.toml
- src/cuga/configurations/memory/memory_settings.mem0.toml
- src/cuga/configurations/models/settings.litellm.toml
- docs/memory/README.md
- src/cuga/configurations/memory/memory_settings.milvus.toml
- README.md
- src/cuga/configurations/models/settings.openai.toml
- src/cuga/configurations/models/settings.azure.toml
- src/cuga/configurations/models/settings.rits.toml
- src/cuga/configurations/models/settings.google.toml
- src/cuga/configurations/models/settings.watsonx.toml
- src/cuga/configurations/models/settings.groq.toml
- src/cuga/configurations/models/settings.openrouter.toml
| def start( | ||
| service: str = typer.Argument( | ||
| ..., | ||
| help="Service to start: demo, demo_skills, demo_knowledge, demo_crm, demo_docs, demo_health, demo_supervisor, manager, registry, appworld, or memory", | ||
| help="Service to start: demo, demo_skills, demo_knowledge, demo_crm, demo_docs, demo_health, demo_supervisor, manager, registry, or appworld", | ||
| ), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add travel_agent back to the help text.
start() still validates and dispatches travel_agent, so omitting it here makes --help inaccurate.
Proposed fix
- help="Service to start: demo, demo_skills, demo_knowledge, demo_crm, demo_docs, demo_health, demo_supervisor, manager, registry, or appworld",
+ help="Service to start: demo, demo_skills, demo_knowledge, demo_crm, demo_docs, demo_health, demo_supervisor, travel_agent, manager, registry, or appworld",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def start( | |
| service: str = typer.Argument( | |
| ..., | |
| help="Service to start: demo, demo_skills, demo_knowledge, demo_crm, demo_docs, demo_health, demo_supervisor, manager, registry, appworld, or memory", | |
| help="Service to start: demo, demo_skills, demo_knowledge, demo_crm, demo_docs, demo_health, demo_supervisor, manager, registry, or appworld", | |
| ), | |
| def start( | |
| service: str = typer.Argument( | |
| ..., | |
| help="Service to start: demo, demo_skills, demo_knowledge, demo_crm, demo_docs, demo_health, demo_supervisor, travel_agent, manager, registry, or appworld", | |
| ), |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/cuga/cli/main.py` around lines 858 - 862, The start() CLI help text is
missing travel_agent even though the command still accepts and dispatches it.
Update the service Argument help string in start() to include travel_agent
alongside the other supported services so --help matches the actual validation
and dispatch behavior.
| "ws": ">=8.21.0", | ||
| "linkify-it": ">=5.0.1", | ||
| "undici": ">=7.28.0" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
linkify-it 5.0.1 security advisory and undici 7.28.0 fixed CVE
💡 Result:
The security status for linkify-it 5.0.1 and undici 7.28.0 as of June 28, 2026, is as follows: linkify-it 5.0.1 Version 5.0.1 of linkify-it was released on May 23, 2026, to address a high-severity Denial of Service (DoS) vulnerability tracked as CVE-2026-48801 [1][2]. This issue involved a structural algorithmic flaw in the LinkifyIt.prototype.match scan loop, which exhibited quadratic O(N²) complexity when processing inputs containing many fuzzy links or emails, allowing malicious input to cause significant CPU exhaustion [3][2]. Additionally, the 5.0.1 release included a fix for an issue where astral character patterns (e.g., emojis) could cause the application to hang when fuzzy matching options were enabled, which was tied to an underlying issue in the uc-micro dependency [1]. undici 7.28.0 Version 7.28.0 of undici was released on June 15, 2026, as a security update addressing multiple vulnerabilities [4]. Notable fixes in this release include: CVE-2026-12151: A high-severity WebSocket Denial of Service vulnerability where the client failed to enforce a limit on the number of WebSocket fragments, leading to memory exhaustion and potential process crashes when processing a stream of many small or empty continuation frames [5][6]. CVE-2026-9678: A high-severity cross-user information disclosure vulnerability in the cache interceptor [7]. The issue occurred when the Cache-Control header used whitespace-padded field names (e.g., private=" authorization"), causing the parser to incorrectly classify responses as cacheable and potentially serve them to unauthorized users in shared-cache modes [7]. Multiple other vulnerabilities were also patched in this release, including CVE-2026-9697, CVE-2026-6734, CVE-2026-9679, CVE-2026-11525, and CVE-2026-6733, covering various security improvements [4].
Citations:
- 1: https://github.com/markdown-it/linkify-it/blob/HEAD/CHANGELOG.md
- 2: GHSA-22p9-wv53-3rq4
- 3: https://advisories.gitlab.com/npm/linkify-it/CVE-2026-48801/
- 4: https://github.com/nodejs/undici/releases/tag/v7.28.0
- 5: https://nvd.nist.gov/vuln/detail/CVE-2026-12151
- 6: https://www.linkedin.com/posts/matteocollina_security-release-for-undici-the-http-activity-7473405174754103296-0Axn
- 7: GHSA-pr7r-676h-xcf6
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== relevant package.json files =="
git ls-files '**/package.json' | sed -n '1,120p'
echo
echo "== src/frontend_workspaces/package.json =="
cat -n src/frontend_workspaces/package.json | sed -n '1,140p'
echo
echo "== root package.json (if present) =="
if [ -f package.json ]; then
cat -n package.json | sed -n '1,180p'
fi
echo
echo "== pnpm workspace/config files =="
git ls-files '.npmrc' '.pnpmfile.cjs' 'pnpm-workspace.yaml' 'pnpm-lock.yaml' | sed -n '1,120p'Repository: cuga-project/cuga-agent
Length of output: 3062
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== node engine declarations =="
rg -n '"engines"|node' src/frontend_workspaces -g 'package.json' -g '.npmrc' -g 'README*' -g '*.md' || true
echo
echo "== direct linkify-it / undici references =="
rg -n '"(linkify-it|undici)"|linkify-it|undici' src/frontend_workspaces -g 'package.json' -g 'pnpm-lock.yaml' -g '*.ts' -g '*.tsx' -g '*.js' -g '*.mjs' -g '*.cjs' || true
echo
echo "== lockfile existence =="
git ls-files 'src/frontend_workspaces/pnpm-lock.yaml' 'pnpm-lock.yaml'Repository: cuga-project/cuga-agent
Length of output: 4605
🏁 Script executed:
#!/bin/bash
set -euo pipefail
lock=src/frontend_workspaces/pnpm-lock.yaml
echo "== undici-related sections =="
rg -n '^(\s{2,})?undici(@|:)|undici-types|cache interceptor|websocket' "$lock" || true
echo
echo "== context around undici package entry =="
line=$(rg -n '^ undici@8\.5\.0:' "$lock" | cut -d: -f1 | head -n1 || true)
if [ -n "${line:-}" ]; then
sed -n "$((line-20)),$((line+40))p" "$lock"
fi
echo
echo "== context around packages depending on undici =="
for pat in 'undici: 8.5.0' 'undici-types: 6.21.0' 'undici-types: 7.16.0'; do
echo "-- $pat --"
rg -n -A4 -B4 "$pat" "$lock" || true
doneRepository: cuga-project/cuga-agent
Length of output: 4726
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Node/runtime mentions across repo =="
rg -n -i '\bnode\b|nvm|volta|asdf|corepack|pnpm@|>= *20|>= *22|Node.js' . \
-g 'package.json' -g '.nvmrc' -g '.node-version' -g '.tool-versions' -g 'README*' -g '*.md' \
| sed -n '1,220p'
echo
echo "== files that may declare engines =="
rg -n '"engines"\s*:\s*\{' . -g 'package.json' | sed -n '1,120p'Repository: cuga-project/cuga-agent
Length of output: 8176
Tighten the undici override to the Node 18-compatible line. linkify-it@5.0.1 is the patched release, and pnpm.overrides will apply both overrides transitively. The undici: >=7.28.0 range is too open here: this lockfile resolves it to 8.5.0, which requires Node >=22.19.0, while src/frontend_workspaces/README.md still documents Node 18+. Cap it below 8.x (or pin the fixed 7.28.0 release) if Node 18 support must remain.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/frontend_workspaces/package.json` around lines 66 - 68, Tighten the pnpm
override for undici in the package manifest so it stays compatible with the
documented Node 18 support. Update the undici entry in package.json to pin the
fixed 7.28.0 release or otherwise cap it below 8.x, and leave the linkify-it
override as-is since it already targets the patched version. Use the existing
pnpm.overrides block to keep the transitive resolution from pulling in the Node
22-only undici 8.x line.
There was a problem hiding this comment.
This removes pymilvus[milvus-lite] from CUGA core, which makes sense for the security/dependency cleanup, but we should preserve an explicit Milvus install path for Evolve.
Right now cuga[evolve] installs only altk-evolve>=1.1.0, and the README/launcher command uses uvx --from altk-evolve ... evolve-mcp. If users set EVOLVE_BACKEND=milvus, Evolve will import pymilvus and fail unless the Milvus extra is installed.
We don't have to support milvus but just write this caveat down if user wants to switch back to the milvus
- Document the Milvus command explicitly:
uvx --from 'altk-evolve[milvus]' --with 'setuptools<70' evolve-mcp - Or add a separate optional extra such as:
evolve-milvus = ["altk-evolve[milvus]>=1.1.0; python_version>='3.12'"]
…pendabot-high-severity-alerts
Reasoning-only backends and post-sandbox empty NL turns left execution_complete true with a blank final_answer, breaking E2E playbook refinement. Fall back to reasoning text and sandbox output.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/cuga/backend/cuga_graph/nodes/cuga_agent_core/graph/shared_nodes.py (1)
244-244: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueStray
ponytail:in the comment.The marker word reads like an accidental placeholder. Reword for clarity.
✏️ Suggested wording
- # ponytail: reasoning-only models may finalize with empty visible content + # Reasoning-only models may finalize with empty visible content🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/cuga/backend/cuga_graph/nodes/cuga_agent_core/graph/shared_nodes.py` at line 244, The comment in shared_nodes.py contains a stray placeholder word in the reasoning-only models note; clean up the wording in the affected comment near the cuga_agent_core graph node logic so it reads naturally and clearly without the accidental marker, while keeping the intent about empty visible content in the reasoning-only finalization path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/cuga/backend/cuga_graph/nodes/cuga_agent_core/graph/shared_nodes.py`:
- Around line 248-257: The END-path fallback in the shared node logic assumes
HumanMessage.content is always a string, but it can also be a list of content
blocks and would fail on startswith. Update the final_answer recovery loop in
shared_nodes.py to guard the type of msg.content before treating it as text,
handling only string content for the exec_prefix check and skipping or safely
normalizing non-string values. Keep the fix localized to the modified_messages
scan in the HumanMessage branch so the fallback remains robust.
---
Nitpick comments:
In `@src/cuga/backend/cuga_graph/nodes/cuga_agent_core/graph/shared_nodes.py`:
- Line 244: The comment in shared_nodes.py contains a stray placeholder word in
the reasoning-only models note; clean up the wording in the affected comment
near the cuga_agent_core graph node logic so it reads naturally and clearly
without the accidental marker, while keeping the intent about empty visible
content in the reasoning-only finalization path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4eab85dd-05c4-4fc0-b613-d434204e3c5d
📒 Files selected for processing (5)
src/cuga/backend/cuga_graph/nodes/cuga_agent_core/graph/shared_nodes.pysrc/cuga/backend/cuga_graph/nodes/cuga_agent_core/tests/graph/test_shared_call_model.pysrc/cuga/backend/cuga_graph/nodes/cuga_lite/adapter/sandbox_node.pysrc/cuga/backend/cuga_graph/nodes/cuga_lite/nl_auto_continue_classifier.pysrc/cuga/cli/main.py
✅ Files skipped from review due to trivial changes (1)
- src/cuga/cli/main.py
| if not (final_answer or "").strip(): | ||
| exec_prefix = "Execution output:\n" | ||
| for msg in reversed(modified_messages): | ||
| if isinstance(msg, HumanMessage): | ||
| text = msg.content or "" | ||
| if text.startswith(exec_prefix): | ||
| body = text[len(exec_prefix) :].strip() | ||
| if body: | ||
| final_answer = body | ||
| break |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
msg.content may not be a str here.
text = msg.content or "" followed by text.startswith(exec_prefix) assumes string content, but HumanMessage.content can be a list of content blocks (the sibling change in nl_auto_continue_classifier.py explicitly handles dict/list blocks). A list-valued content would raise AttributeError and crash the node on the END path. In practice execution-output messages are string-built, so risk is low, but a guard keeps this robust.
🛡️ Proposed guard
for msg in reversed(modified_messages):
if isinstance(msg, HumanMessage):
text = msg.content or ""
+ if not isinstance(text, str):
+ continue
if text.startswith(exec_prefix):📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if not (final_answer or "").strip(): | |
| exec_prefix = "Execution output:\n" | |
| for msg in reversed(modified_messages): | |
| if isinstance(msg, HumanMessage): | |
| text = msg.content or "" | |
| if text.startswith(exec_prefix): | |
| body = text[len(exec_prefix) :].strip() | |
| if body: | |
| final_answer = body | |
| break | |
| if not (final_answer or "").strip(): | |
| exec_prefix = "Execution output:\n" | |
| for msg in reversed(modified_messages): | |
| if isinstance(msg, HumanMessage): | |
| text = msg.content or "" | |
| if not isinstance(text, str): | |
| continue | |
| if text.startswith(exec_prefix): | |
| body = text[len(exec_prefix) :].strip() | |
| if body: | |
| final_answer = body | |
| break |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/cuga/backend/cuga_graph/nodes/cuga_agent_core/graph/shared_nodes.py`
around lines 248 - 257, The END-path fallback in the shared node logic assumes
HumanMessage.content is always a string, but it can also be a list of content
blocks and would fail on startswith. Update the final_answer recovery loop in
shared_nodes.py to guard the type of msg.content before treating it as text,
handling only string content for the exec_prefix check and skipping or safely
normalizing non-string values. Keep the fix localized to the modified_messages
scan in the HumanMessage branch so the fallback remains robust.
Summary
pymilvus[milvus-lite]from core deps and bump setuptools 69 → 81 (fixes alerts [Feature] Knowledge v1: in-process engine, scoped corpora, and SDK integration #129, fix: reconcile litellm 1.83.4 with optional openlit and UBI Docker #130)Memory cleanup (cc @gaodan-fang @gjt-prog)
The legacy agentic-memory subsystem was removed in #153 (
34755398), butpymilvus[milvus-lite]stayed in core deps — forcingsetuptools<70and shipping ~25–55 MB platform wheels for code nothing imported.This PR finishes that cleanup:
pymilvus[milvus-lite]and the unusedmemoryoptional extra (mem0ai)src/cuga/configurations/memory/*,docs/memory/README.md, and stale[memory.*]blocks from model settingscuga start memoryanduv sync --extra memoryRuntime memory today: knowledge uses sqlite-vec/pgvector; user preferences use Evolve — neither touched Milvus. Stub
/api/config/memoryendpoints remain (no-op) for UI compat.Still risk-accepted: nltk (#481) — dev-only, no upstream patch.
Test plan
uv syncpnpm installinsrc/frontend_workspacesSummary by CodeRabbit