backend: bump langchain stack to 1.x for 2 HIGH + 3 MEDIUM CVEs#7149
backend: bump langchain stack to 1.x for 2 HIGH + 3 MEDIUM CVEs#7149
Conversation
The single remaining `from langchain.schema import …` in our code moves to the canonical `from langchain_core.messages import …`. The classes are identical (verified with `is` comparison): the `langchain.schema` module has been a re-export of `langchain_core.messages` since 0.1.x and is removed entirely in the langchain 1.x line. Doing this migration first as a no-op refactor under the existing 0.3.x langchain pin keeps the subsequent langchain-core 1.x bump as a pure dep change. Verified with docker test image rebuild + 190-test baseline subset all green.
Closes: - HIGH CVE-2026-34070 — langchain-core 0.3.84 -> 1.3.2 - HIGH CVE-2025-64439 — langgraph-checkpoint 2.1.2 -> 4.0.0 - MEDIUM CVE-2026-28277 — langgraph 0.6.10 -> 1.0.10 - MEDIUM CVE-2026-27794 — langgraph-checkpoint same bump (4.x covers both HIGH 64439 and MEDIUM 27794) - MEDIUM CVE-2026-41481 — langchain-text-splitters 0.3.11 -> 1.1.2 Headline bumps + locked-in cascade. langchain 1.x and langgraph 1.x are entangled (langgraph-prebuilt 1.0.8 requires langchain-core>=1.0.0, langchain-text-splitters 1.1.2 requires langchain-core>=1.2.31), so they must move as a single resolver-satisfiable set. | Package | Was -> Now | Reason | | langchain-core | 0.3.84 -> 1.3.2 | HIGH CVE; required by langchain-text-splitters 1.1.2 | | langchain | 0.3.27 -> 1.2.9 | locked to langchain-core 1.x | | langchain-community | 0.3.31 -> 0.4.1 | locked to langchain-core 1.x | | langchain-openai | 0.3.35 -> 1.1.9 | locked; held below 1.1.10 to avoid openai 2.x cascade | | langchain-google-genai | 2.1.12 -> 3.2.0 | locked to langchain-core 1.x | | langchain-pinecone | 0.2.12 -> 0.2.13 | locked; opens to langchain-core 1.x in 0.2.13 | | langchain-text-splitters | 0.3.11 -> 1.1.2 | MEDIUM CVE | | langgraph | 0.6.10 -> 1.0.10 | MEDIUM CVE | | langgraph-checkpoint | 2.1.2 -> 4.0.0 | HIGH + MEDIUM CVE in one bump | | langgraph-prebuilt | (transitive) -> 1.0.8 | new explicit pin; required by langgraph 1.0 | | langgraph-sdk | 0.2.9 -> 0.3.0 | required by langgraph 1.0 | Cascade pins outside the langchain stack: - openai 1.104.2 -> 1.109.1 — langchain-openai 1.1.9 requires openai>=1.109.1; held within 1.x to defer the openai 2.x migration (and its associated LOW CVE-2026-41488 in langchain-openai 1.1.14) to a separate PR. - pydantic 2.8.2 -> 2.11.10 — langchain-pinecone 0.2.13 requires pydantic>=2.11.1. - pydantic_core 2.20.1 -> 2.33.2 — pydantic 2.11.10 hard-pins pydantic-core==2.33.2. - typing_extensions 4.12.2 -> 4.15.0 — langchain-core 1.x uses the TypedDict `extra_items` keyword (added in typing_extensions 4.13); without this bump, every utils/llm/* and utils/retrieval/* module fails at import with `_TypedDictMeta.__new__() got an unexpected keyword argument 'extra_items'`. Verified: 1. docker test image rebuild succeeds with all 14 packages at the pinned versions (above). 2. 190-test baseline subset all green. 3. All 28 langchain-importing modules under utils/llm/, utils/retrieval/, utils/observability/ load cleanly (only DefaultCredentialsError on modules that touch GCP at import time, expected in test env).
|
@morpheus review — Approved ✅ 2-file diff: one import migration in Commit 1: Confirmed Commit 2: 11 langchain-stack packages move as one resolver-satisfiable set (entangled pins make partial bumps impossible — documented). 4 cascade pins held to minimums:
Risk profile: pydantic 2.8→2.11 and typing_extensions 4.12→4.15 are foundational packages with wide blast radius, but both are backward-compatible within their major lines. The 190-test baseline + 28-module import smoke passing gives adequate coverage. Deferred items correctly scoped: langchain-openai 1.1.14 (LOW CVE, requires openai 2.x) explicitly parked. No forward references. 2 atomic commits, clean separation of concerns. Labels set. |
Greptile SummaryThis PR closes 2 HIGH and 3 MEDIUM CVEs by bumping the entire langchain ecosystem from 0.3.x to 1.x (11 packages) plus 4 cascade pins, and migrates the one deprecated Confidence Score: 4/5Safe to merge; all findings are P2 quality concerns with no present defects in the changed code. The import change is correct and verified to be the only instance of the deprecated path. The version matrix is logically consistent and backed by a documented smoke-import test over 28 modules. The only open item is that pydantic-settings==2.10.1 was not explicitly called out as a verified cascade pin alongside pydantic 2.11.10, which is a P2 concern but not a blocking defect. backend/requirements.txt — verify pydantic-settings==2.10.1 compatibility with pydantic==2.11.10. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[PR: langchain stack 0.3→1.x] --> B[Commit 1: persona.py
langchain.schema → langchain_core.messages]
A --> C[Commit 2: requirements.txt
11 ecosystem + 4 cascade pins]
B --> D{Other deprecated
langchain.schema imports?}
D -->|None found| E[✅ Migration complete]
C --> F[langchain-core 0.3.84→1.3.2
CVE-2026-34070 HIGH]
C --> G[langgraph-checkpoint 2.1.2→4.0.0
CVE-2025-64439 HIGH + CVE-2026-27794 MEDIUM]
C --> H[langgraph 0.6.10→1.0.10
CVE-2026-28277 MEDIUM]
C --> I[langchain-text-splitters 0.3.11→1.1.2
CVE-2026-41481 MEDIUM]
C --> J[Cascade: openai 1.104.2→1.109.1
held at 1.x to defer openai 2.x]
C --> K[Cascade: pydantic 2.8.2→2.11.10
pydantic_core 2.20.1→2.33.2]
C --> L[Cascade: typing_extensions 4.12.2→4.15.0
fixes TypedDict extra_items regression]
J --> M[⚠️ CVE-2026-41488 DEFERRED
langchain-openai 1.1.14 needs openai 2.x]
Reviews (1): Last reviewed commit: "Bump langchain ecosystem to 1.x for HIGH..." | Re-trigger Greptile |
| pycparser==2.22 | ||
| pydantic==2.8.2 | ||
| pydantic==2.11.10 | ||
| pydantic-settings==2.10.1 |
There was a problem hiding this comment.
pydantic-settings==2.10.1 is held while pydantic advances to 2.11.10 and pydantic_core to 2.33.2. The PR description lists all cascade pins carefully, but pydantic-settings isn't mentioned. While pydantic-settings 2.10.x typically declares a broad pydantic>=2.x dependency and is likely compatible, it's worth confirming this pair was covered by the 28-module smoke-import test (Settings-derived config classes are used in utils/llm/clients.py and friends).
Summary
2 atomic commits closing the deferred langchain-stack CVEs from the Artifact Registry scan on
gcr.io/based-hardware/backend@sha256:348e17d6…. langchain ecosystem moves from the 0.3.x line to 1.x as one resolver-satisfiable set; tight inter-package pins (e.g.langgraph-prebuilt 1.0.8requireslangchain-core>=1.0.0,langchain-text-splitters 1.1.2requireslangchain-core>=1.2.31) make a partial bump impossible.utils/llm/persona.py— single deprecatedfrom langchain.schemaimport →from langchain_core.messages(no-op under 0.3.x; required for 1.x wherelangchain.schemais removed)Closed:
Locked-in cascade (langchain stack)
Cascade pins outside the langchain stack
extra_itemskeyword (added in typing_extensions 4.13). Without this bump, everyutils/llm/*andutils/retrieval/*module fails at import with_TypedDictMeta.__new__() got an unexpected keyword argument 'extra_items'. Caught via post-bump module-import smoke test, not the unit subsetAll cascade bumps held to the smallest version that resolves the conflict.
Code change in commit 1
The single deprecated path in our code (
from langchain.schema import SystemMessage, HumanMessage, AIMessageinutils/llm/persona.py:5) moves tofrom langchain_core.messages import …. The classes are identical (verified withiscomparison):langchain.schemahas been a re-export oflangchain_core.messagessince 0.1.x and is removed entirely in the langchain 1.x line. Doing the migration under the existing 0.3.x pin keeps the bump commit a pure dep change.Out of scope (deferred)
Test plan
For the bump commit:
requirements.txt(15 pinned + 1 new pin)Dockerfile.test(Python 3.11-slim, requirements.txt minus the source-builtlc3py) — only the pip install layer rebuildsutils/llm/,utils/retrieval/,utils/observability/that imports any langchain-* package (28 modules) — catches API/typing regressions that the baseline subset doesn't exerciseAll commits individually green:
DefaultCredentialsErroron modules that touch GCP at import time, expected in test env without service account)Verifying after deploy
/health, an LLM-powered route (chat or memory generation), and a retrieval-tool route (calendar or memory search) to confirm the langchain 1.x runtime APIs behave correctly under real LLM traffic.