13740 Commits

Author SHA1 Message Date
110bea8281 Merge release-1.9.5 into main 2026-06-01 16:40:57 -07:00
59981246de fix: remove duplicate base uv.lock from workflows (forward-port #13326 to main) (#13427)
fix: remove duplicate uv.lock from workspace member

Forward-port of #13326 to main. The monorepo should keep only one
uv.lock at the workspace root; src/backend/base/uv.lock was a stale
duplicate. The scheduled nightly build runs from main's workflow
definition, so create-nightly-tag still ran
`git add ... src/backend/base/uv.lock` against a tree where the file
no longer exists, failing with exit 128.

- Delete src/backend/base/uv.lock
- nightly_build.yml: drop base-dir `uv lock` regeneration and the
  base lockfile from `git add`
- Remove COPY/bind-mount of the base lockfile from all Dockerfiles
- Makefile: lock_base/lock now lock only the root workspace
- changes-filter.yaml: drop the base lockfile path
- .secrets.baseline: shift nightly_build.yml line number 305 -> 304

Fixes the failing nightly:
https://github.com/langflow-ai/langflow/actions/runs/26699469476
2026-05-30 21:07:00 -07:00
601a3e30e2 ci: port safe workflow fixes from release-1.10.0 to main (#13401)
* ci: port safe workflow fixes from release-1.10.0 to main

Reconciles the workflow/CI improvements that landed on release-1.10.0 back
into main, EXCLUDING workflows that depend on release-only features not yet
present on main.

Ported (verified no release-only dependencies):
- test-coverage-advisor.yml (new; advisory-only, fully self-contained)
- ci.yml, nightly_build.yml, db-migration-validation.yml (incl. the #13249
  enhancements), python_test.yml (Python 3.14 support), cross-platform-test.yml
  (--prerelease=if-necessary-or-explicit), lint-js.yml, py_autofix.yml,
  typescript_test.yml

Held back (depend on features that only exist on release-1.10.0):
- extension-migration-checks.yml (extensions / src/bundles / scripts/migrate)
- gp-backend-check.yml (release-only scripts/gp/*.py + backend locales/en.json)
- regression-stub.yml (release-only regressions/ tracking)
- gp-download.yml / gp-upload.yml backend-translation steps
  (release-only scripts/gp/{download,upload}.py)

These converge with main once release-1.10.0 ships. 3-way merged from the
common ancestor; the diff was verified to introduce zero references to
release-only paths.

* test: add cache_dir to Settings EXPECTED_FIELDS snapshot

The diskcache-removal change added a `cache_dir` field to the cache settings group,
but the field-count guard in test_settings_composition.py (EXPECTED_FIELDS, frozen by
the settings split in #13141) was never updated. As a result test_field_count_unchanged
failed on main with `assert 106 == 105`. Add "cache_dir" to the snapshot so it matches
the live Settings model (106 fields).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 15:38:20 -07:00
b410b54294 chore: update starter projects 2026-05-27 14:33:16 -04:00
8c7fe0ac3a chore: bump versions
bump package versions
2026-05-27 14:25:54 -04:00
6a43888915 fix: change docling remote component to receive task id and to throw processing errors (#13353)
* change docling remote component to receive task id and to throw processing errors

* fix: small bug fix tweaks

* fix: report from rafael

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* fix: Global variable selection in tableinput rows

* fix: merge release branch

---------

Co-authored-by: Eric Hare <ericrhare@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-27 09:58:21 -07:00
6923ca24c4 Merge release-1.9.4 into main
# Conflicts:
#	.secrets.baseline
#	src/lfx/src/lfx/_assets/component_index.json
#	src/lfx/src/lfx/services/settings/base.py
2026-05-27 08:43:43 -07:00
1e68de7c2a fix(agent): Force streaming on Agent LLM so tokens stream incrementally (#13356)
* add streaming on agent default back

* [autofix.ci] apply automated fixes

* fix streaming backward compatibility

* ruff style and checker

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-27 12:06:42 -03:00
75b3cc9f6d chore: upgrade uv.lock 2026-05-26 13:14:23 -04:00
87039b46d3 fix: port chroma collection hardening (#13339)
* fix: port chroma collection hardening

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-26 08:08:19 -07:00
26736d6d7d fix: align diskcache removal port 2026-05-26 10:59:31 -04:00
0a5f25f32b chore: port Remove the diskcache dependency
port of https://github.com/langflow-ai/langflow/pull/12953
2026-05-26 10:59:31 -04:00
e192f91eeb fix: ChatBedrock playwright failures 2026-05-25 23:35:48 -04:00
23f3453a65 [autofix.ci] apply automated fixes 2026-05-25 23:35:48 -04:00
7ac198ac37 chore: update opik, perplexity , weaviate 2026-05-25 23:35:48 -04:00
00fe8c001c chore: dup langchain-qdrant to langchain-mongodb 2026-05-25 23:35:48 -04:00
a752275fbd chore: add to deps and loose missing test 2026-05-25 23:35:48 -04:00
a7ae55e5d5 [autofix.ci] apply automated fixes 2026-05-25 23:35:48 -04:00
9224534f70 chore: port over mem0ai changes from 1.10.0
https://github.com/langflow-ai/langflow/pull/13292
2026-05-25 23:35:48 -04:00
cb6d09fc5d chore: update pkg in test_all_modules_importable 2026-05-25 23:35:48 -04:00
1bae798321 [autofix.ci] apply automated fixes 2026-05-25 23:35:48 -04:00
d5bdc6175f chore: update test_all_modules_importable 2026-05-25 23:35:48 -04:00
a11ef3113b [autofix.ci] apply automated fixes 2026-05-25 23:35:48 -04:00
c2b440cede chore: update qdrant 2026-05-25 23:35:48 -04:00
71567829f5 fix: use langchain-mongodb
use langchain-mongodb instead of depricated langchain_community.vectorstores for MongoDBAtlasVectorSearch import
2026-05-25 23:35:48 -04:00
c34b79f3c7 chore: update pymongo 2026-05-25 13:57:05 -04:00
e2c30451d2 chore: update uv.locks 2026-05-25 13:29:36 -04:00
bd926ca3d4 refactor(settings): split monolithic Settings into per-domain group mixins (#13141)
* refactor(settings): split monolithic Settings into per-domain group mixins

Move the ~70-field Settings class from one 755-line base.py into 13 cohesive
BaseModel mixins under lfx/services/settings/groups/ (paths, server, database,
cache, storage, mcp, telemetry, observability, security, components, ui,
runtime, variables). Settings now composes them via multiple inheritance.

Inheritance order is chosen so cross-group validators see their dependencies
in info.data: PathSettings rightmost (config_dir before database_url),
ServerSettings just left of it (workers before event_delivery).

No env var or call-site changes. BASE_COMPONENTS_PATH re-export preserved for
tests that import it transitively.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* docs(settings): fix wrong mcp_server_timeout docstring and idle-timeout comment

mcp_server_timeout's docstring was copy-pasted from a database setting and
mentioned 'lock to released' / 'database connection'. Replace with text that
describes the actual field.

mcp_session_idle_timeout's comment said 'Defaults to 5 minutes' but 400s is
~6.7 minutes. Drop the misleading 'minutes' claim and keep the value.

* test(settings): add structural safety tests for the group composition

Adds 26 tests to guard the refactor:

- All 105 fields that lived on the monolithic Settings still exist on the
  composed class. A missing group in the inheritance list trips this loudly.
- A sampling of critical scalar and dict defaults (host, port, workers,
  cache_type, sqlite_pragmas, db_connection_settings, etc.) are byte-for-byte
  unchanged.
- Cross-group validator dependencies still resolve via info.data:
  workers > 1 forces event_delivery=direct (ServerSettings -> RuntimeSettings)
  and database_url falls back to a sqlite path under config_dir without
  raising 'config_dir not set' (PathSettings -> DatabaseSettings).
- A parametrized sweep verifies a representative set of LANGFLOW_* env vars
  still populate their fields.
- Back-compat exports (CustomSource, is_list_of_any, yaml helpers,
  BASE_COMPONENTS_PATH) are still importable from settings.base.
- update_settings handles scalars and list-with-no-duplicates correctly.
- save_settings_to_yaml round-trips without error.

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-25 13:37:29 +00:00
7f8bd2d432 chore: update versions and revert dockerfile npm 2026-05-25 09:18:30 -04:00
5168c9f3ef chore: upgrades and docker file changes 2026-05-25 09:18:30 -04:00
0ba4c3725d chore: mass dep update 2026-05-25 09:18:30 -04:00
c5816cef34 fix: upgrade dependencies for security fixes (#13218)
* chore: upgrade dependencies for security fixes

- Upgrade authlib from 1.7.0 to 1.7.2
- Update Docker build to use Node.js 22.x (includes npm 10.9+)
- Update uv.lock with latest dependency versions

* chore: run npm audit fix

run npm audit fix

---------

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
Co-authored-by: Adam Aghili <Adam.Aghili@ibm.com>
2026-05-20 11:18:50 -04:00
2ff17eca24 fix: Model handling for tool calling in agents and update IBM models (#13191)
* Model handling for tool calling in agents and update IBM models

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-18 21:35:37 +00:00
322e4908b9 fix: backport policies ToolGuard lazy imports (#13144)
fix: backport policies toolguard lazy imports
2026-05-15 09:24:55 -07:00
b695f97cd3 fix: More python 3.14 compatibility cleanup 2026-05-14 17:49:56 -07:00
cf488e545c fix: Gate more tests on package presence 2026-05-14 17:15:37 -07:00
5fec0a1a42 fix: Skip Python 3.14 incompatible watsonX imports 2026-05-14 16:50:30 -07:00
ecadc106d0 fix: Python 3.14 fallback for baidu 2026-05-14 16:19:03 -07:00
f2b028f28b fix: update gunicorn constraint to allow version 26.x
- Update gunicorn constraint from <26.0.0 to <27.0.0
- Resolves dependency check failure with gunicorn 26.0.0
- Regenerate uv.lock with updated constraint
2026-05-14 18:01:34 -04:00
22e9003bec fix: correct version numbers for 1.9.3 patch release
- langflow-base: 0.10.0 -> 0.9.3
- lfx: 0.5.0 -> 0.4.3 (and dependency reference)
- sdk: 0.2.0 -> 0.1.3
2026-05-14 16:56:00 -04:00
e16c99d031 fix: upgrade langchain-classic to 1.0.7 (#13130)
chore: upgrade langchain-classic to 1.0.7

- Update version constraint from ~=1.0.0 to ~=1.0.7
- Fixes issues present in version 1.0.4
- Update uv.lock with new dependency resolution

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
2026-05-14 16:51:35 -04:00
d5ef588e42 chore: bump versions to 1.9.3 2026-05-14 15:41:43 -04:00
a80cf1c649 chore: support Python 3.14 (#13085)
* feat: upgrade Docker images to Python 3.14 (experimental)

- Update pyproject.toml: requires-python from <3.14 to <3.15
- Update all 5 Dockerfiles to use Python 3.14:
  - Builder stage: python3.12-trixie-slim → python3.14-trixie-slim
  - Runtime stage: python:3.12-slim-trixie → python:3.14-slim-trixie

- src/backend/base/pyproject.toml
- docker/build_and_push_base.Dockerfile
- docker/build_and_push.Dockerfile
- docker/build_and_push_backend.Dockerfile
- docker/build_and_push_with_extras.Dockerfile
- docker/build_and_push_ep.Dockerfile

Python 3.14.5 was released on May 10, 2026. Upgrading to the latest
Python version should help reduce CVE vulnerabilities in Docker images.

This is an experimental change to test Python 3.14 compatibility:
- Docker images will use Python 3.14
- CI/CD workflows still test on Python 3.10-3.13
- Nightly build will validate if dependencies work with 3.14
- Can be reverted quickly if issues are found

- Monitor nightly build for failures
- If successful, update CI/CD workflows to add Python 3.14 to test matrix
- If failures occur, revert and investigate compatibility issues

* chore: support Python 3.14

Bump requires-python upper bound to <3.15 across langflow, langflow-base,
lfx, and langflow-sdk, and add 3.14 to CI test matrices so PRs are gated
on 3.14 compatibility.

Conditional pins for transitive deps without 3.14 wheels at the existing
caps:
- onnxruntime: >=1.26 on 3.14 (existing <1.24 cap retained for 3.10)
- faiss-cpu: >=1.13.2 on 3.14 (existing ==1.9.0.post1 retained for <3.14)

* chore: marker-gate IBM watsonx packages for Python 3.14

ibm-watsonx-ai 1.3.x cannot import on Python 3.14: its StrEnum subclasses
override __init__ in a way that conflicts with 3.14's reworked enum
__set_name__ path (TypeError on KnowledgeBaseFieldRole class creation).

Cap ibm-watsonx-ai, langchain-ibm, and the ibm-watsonx-orchestrate-*
extras at python_version<'3.14' until upstream adapts. Watsonx component
imports are already lazy, so this surfaces only at component-access time
on 3.14, where the existing ImportError handler in
lfx.components.ibm.__init__ degrades it gracefully.

test_model_utils.py imports ChatWatsonx at module top to verify
get_model_name resolves model_id; guard that import so the test
module skips on 3.14 instead of breaking collection.

* [autofix.ci] apply automated fixes

* chore: upgrade remaining Docker images to Python 3.14

build_and_push*.Dockerfile already moved to 3.14 in the merge from
feat/upgrade-python-3.14-docker-images. Apply the same bump to the
dev, devcontainer, and lfx Docker images so all in-repo Dockerfiles
share one Python version.

* [autofix.ci] apply automated fixes

* chore: gate 3.14-broken extras to python_version<'3.14'

cuga (and its transitive fastembed -> py-rust-stemmers source build),
altk/agent-lifecycle-toolkit (re-pulls ibm-watsonx-ai which was already
gated), langchain-pinecone, langwatch, ragstack-ai-knowledge-store, and
OpenDsStar all pin themselves below 3.14 upstream. Without a marker
guard, the workspace lock still tries to install them and a Docker
`uv sync` then attempts source builds that require Rust (CI Docker
test failure with py-rust-stemmers 0.1.5).

Add python_version<'3.14' (or <'3.13' for ragstack) to each pin so
those packages are simply omitted from the 3.14 install set until
upstream catches up. uv pip check is now clean on 3.14.2.

* test: skip test_altk_agent on Python 3.14

altk (agent-lifecycle-toolkit) is gated to python_version<'3.14'
upstream and now via the langflow-base [altk] extra marker. The test
imports altk at module top to exercise ALTKAgentComponent; guard the
import so collection skips on 3.14 instead of failing.

* test: skip remaining altk tests on Python 3.14

Three more test modules import lfx.base.agents.altk_* at module top,
which transitively imports altk. Add the same module-level skip guard
as test_altk_agent.py:
- test_altk_agent_logic.py
- test_altk_agent_tool_conversion.py
- test_conversation_context_ordering.py

* fix(calculator): replace removed ast.Num with ast.Constant for Python 3.14

ast.Num was deprecated in Python 3.8 in favor of ast.Constant and
removed entirely in 3.14. The calculator tool and its core walker
crashed on 3.14 with 'module ast has no attribute Num'.

Switch the isinstance checks to ast.Constant + isinstance(node.value,
(int, float)), and drop the now-dead ast.Num backwards-compat branch
in calculator_core.py (the ast.Constant branch already handles every
input it would have matched). Update the parser unit-test fixtures
to construct ast.Constant nodes.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* test: skip LangWatch HTTP instrumentation tests on Python 3.14

langwatch is gated to python_version<'3.14' upstream. The
TestLangWatchHttpInstrumentation class patches langwatch.setup and
langwatch.trace inside a fixture, which requires langwatch to be
importable; on 3.14 the test errors with ModuleNotFoundError.

Guard the class with a skipif on langwatch availability.

* test: allow IBM and altk components to be missing on Python 3.14

test_all_modules_importable enforces that every component in __all__
imports cleanly. On 3.14 the ibm-watsonx-ai, langchain-ibm, and altk
packages are gated upstream and intentionally not installed, so the
WatsonxAI, WatsonxEmbeddings, and ALTKAgent components fail to import
as designed.

- test_all_components_in_categories_importable: accept a known-gated
  deny-list on 3.14 instead of failing.
- test_all_lfx_component_modules_directly_importable: extend the
  existing 'missing optional dependency' allowlist with altk,
  langchain_ibm, and ibm_watsonx_ai.

* fix(lfx): pass ensure_exists to user_cache_dir for Python 3.14

Python 3.14 tightened PurePath.__init__ to reject unknown keyword
arguments. The KeyedWorkerLockManager constructor was passing
ensure_exists=True to Path() instead of user_cache_dir(), which
silently worked on 3.10-3.13 but raises TypeError on 3.14 and also
meant the cache directory was never actually being created.

Move the kwarg to user_cache_dir() where it belongs and update the
two unit tests that asserted the buggy call shape.

* [autofix.ci] apply automated fixes

* test: accept either ZIP or JSON error path on Python 3.14

Python 3.14's zipfile.is_zipfile() now validates the central-directory
signature in addition to EOCD, so the garbage+EOCD payload no longer
passes the is_zipfile() dispatch in the /flows/upload/ route. The
endpoint still returns 400 with a descriptive detail (now from the JSON
branch); only the message wording differs, which the test was asserting
verbatim.

* fix(lfx): normalize cors_origins ['*'] back to '*' on Python 3.14

Pydantic-settings on Python 3.14 parses the env var '*' into ['*']
before the cors_origins field validator runs (the list[str] | str union
resolves differently than on 3.10-3.13). Collapse that back to the
bare-string wildcard so downstream consumers — including
warn_about_future_cors_changes and the test suite — see the same shape
on every supported Python version.

---------

Co-authored-by: vijay kumar katuri <vijay.katuri@ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
(cherry picked from commit 1955f8fae5)
2026-05-13 22:23:39 +00:00
cd4aa718e7 fix: stabilize model toggle and refresh Agent dropdown after provider changes (#13113)
* fix: stabilize model toggle and refresh Agent dropdown after provider changes

Two related regressions in the Model Provider management flow on
release-1.9.3:

1. Toggle bounce — rapid clicks on a model Switch flickered between on
   and off before settling. ``handleModelToggle`` performed an
   optimistic ``setQueryData`` on ``useGetEnabledModels`` but never
   cancelled in-flight refetches. With React Query defaults
   (``staleTime: 0``, ``refetchOnWindowFocus: true``), a background
   refetch could land mid-debounce and overwrite the optimistic state
   with stale server data, then the deferred mutation eventually
   corrected it. Fix: ``cancelQueries`` before each optimistic update,
   per the canonical TanStack Query optimistic-updates pattern.

2. Agent dropdown stayed stale after the provider modal closed —
   disabled models remained listed in the Agent's Language Model
   dropdown. The post-close ``isRefreshingAfterClose`` loading gate
   only waited for ``useGetModelProviders`` to settle, not
   ``useGetEnabledModels``. When the providers refetch finished first,
   the loading state cleared and ``groupedOptions`` ran against the
   still-stale enabled-models cache. Fix: track both queries'
   ``isFetching`` flags in the gate's effect.

No behavioral change to the sticky-default UX — the user's previously
selected model continues to show in the dropdown with the wrench
affordance when globally disabled, as designed.

Also narrows the pre-existing ``catch (error: any)`` patterns in the
edited hook file to ``unknown`` with a small shared ``getErrorMessage``
helper, satisfying the staged-file no-explicit-any pre-commit lint.

Tests:
- New ``useProviderConfiguration`` unit test asserts
  ``cancelQueries`` runs before ``setQueryData`` on toggle.
- Extended ``ModelInputComponent`` test covers the dual-query loading
  gate (providers settles first, enabled-models still in flight →
  loading persists; then enabled-models settles → loading clears).

* fix: re-apply pending overlay through entire mutation lifecycle

Addresses review feedback on #13113: ``cancelQueries`` only cancels
refetches that are already in flight at click time. A new
``useGetEnabledModels`` refetch can still start during the 1s
debounce window (or while the mutation is in flight) and overwrite
the optimistic cache with stale server state, producing the same
bounce we just fixed.

Two coordinated changes keep the optimistic state protected for the
entire pending-toggle window:

1. ``pendingModelToggles`` is no longer cleared upfront when the
   debounced flush sends a mutation. Instead, ``clearSentToggles``
   removes only the entries whose value still matches what we sent
   on ``onSettled`` / ``onError``. This preserves the overlay across
   the in-flight mutation window AND correctly handles the case
   where the user re-toggled the same model mid-flight (now a fresh
   intent that survives clearing).

2. A new ``useEffect`` subscribes to ``useGetEnabledModels`` and
   re-applies the pending overlay whenever the data emission drifts
   from the user's pending intent. This catches any refetch
   (window focus, mount, reconnect, stale-time expiry) that lands
   between click and ``onSettled``, regardless of when it started.

Tests:
- New ``re-applies the pending overlay when a refetch surfaces
  stale data`` test simulates a stale refetch and asserts the
  effect re-applies the optimistic overlay.
- New ``does not re-overlay when no toggles are pending`` test
  guards against spurious overlay calls on mount.

* fix: split overlay vs unsent buffers to prevent duplicate model toggle mutations

Addresses a follow-up race introduced by the previous commit: keeping
``pendingModelToggles`` populated through ``onSettled`` (so the
re-overlay effect could repel mid-flight refetches) also caused the
next flush to snapshot the in-flight entries again, sending duplicate
requests with non-deterministic success/failure ordering. The same
risk applied to ``flushPendingChanges`` on modal close.

Split the single buffer into two refs with single responsibilities:

  - ``overlayToggles``: the union of every toggle still protecting the
    UI. The re-overlay effect re-applies this whenever
    ``useGetEnabledModels`` emits new data. Drained per-key on
    ``onSettled``/``onError`` only when the overlay value still matches
    what we sent (a user re-toggle mid-flight becomes a fresh intent
    and must survive the clear).

  - ``unsentToggles``: the strict subset that has NOT been sent in a
    mutation yet, or was re-toggled since the last send. Drained
    immediately at flush time so subsequent flushes never resend an
    in-flight payload.

``handleModelToggle`` populates both buffers; flushes drain only
``unsentToggles`` and use ``overlayToggles`` for cache protection.

Two new unit tests:
- ``does not resend in-flight toggles when a new toggle is flushed``
  asserts that after toggling A then B (with A's mutation in flight),
  the second flush carries ONLY B.
- ``re-sends a model when the user re-toggles it after the previous
  flush fired`` asserts that re-toggling the same model produces a
  second mutation (the re-toggle is a fresh intent, not a duplicate).

* fix: drop sticky-default UX, treat disabled-selected model like any other

Removes the sticky-default carve-out so a globally-disabled model is
never shown in the Agent's Language Model dropdown, regardless of
whether it's the node's saved selection. Drops the Wrench/Configure
affordance — there's no per-trigger "this model isn't enabled for
your user" UX anymore; the dropdown is the single source of truth.

Changes in ``modelInputComponent``:

  - ``groupedOptions``: drop the ``isStickyNotEnabled`` filter
    bypass and the zero-provider import fallback. Disabled models
    never pass the filter, even when tagged ``not_enabled_locally``.

  - ``selectedModel``: drop the saved-value preservation branch.
    If the saved name isn't in ``flatOptions``, fall through to the
    first available option (or ``null`` if nothing is available).

  - Auto-select effect: fires whenever the saved value isn't in
    ``flatOptions``, not just when the value is empty. This
    realigns the node's stored value with the trigger so the
    rendered selection and the run-time selection don't diverge.

  - ``hasEnabledProviders``: redefined as "at least one model of
    this component's type is enabled across any provider"
    (derived from ``groupedOptions``). Routes a configured-but-
    all-disabled provider to the Setup Provider CTA — same UX as
    the never-configured case.

  - Remove the Wrench JSX, the ``showConfigureAffordance``
    derivation, and the now-orphaned ``hasProcessedEmptyRef``.

Tests:
  - ``renders the Setup Provider CTA when no models are enabled``
    (replaces the old disabled-combobox expectation).
  - ``auto-selects an available model when the saved value is
    globally disabled``.
  - ``renders the Setup Provider CTA when a provider is configured
    but all its models are disabled``.
  - ``never renders the Configure wrench affordance``.

* refactor: extract toggle queue into useModelToggleQueue hook

Addresses review I1 (file size + mixed responsibilities) and R1, R2,
R3, R4 in one pass.

I1 — Extract toggle-queue logic out of useProviderConfiguration. The
parent hook drops from 821 lines to 601 and now owns a single
responsibility (variable CRUD + provider lifecycle). The toggle queue
— overlay/unsent buffers, debounced flush, awaitable flush, optimistic
cache management, re-overlay effect — lives in a new 292-line
useModelToggleQueue.ts with one clear responsibility.

R1 — Inside the new hook, DRY the two flush variants behind shared
helpers:
  - ``buildAndConsumeToggleBatch()`` snapshots unsentToggles into the
    mutation payload, captures the pre-toggle cache for rollback, and
    drains unsentToggles atomically.
  - ``rollbackToggleBatch()`` drains overlay BEFORE restoring
    previousData (load-bearing order — otherwise the re-overlay effect
    would re-apply the stale overlay over the rollback).
The two flush callers now differ only in ``mutate`` vs awaitable
``mutateAsync`` plumbing.

R2 — Explicit loop-guard comment on the drift check inside the
re-overlay effect. Names the ``drifted`` short-circuit as the
termination condition so a future refactor that "simplifies" to an
unconditional re-apply doesn't silently introduce a render loop.

R3 — Adversarial coverage for the mutation error path:
  - ``rolls back to previousData when the toggle mutation fails``
  - ``does not re-apply the overlay after a failed mutation drains it``
    (asserts the drain-before-rollback ordering)
  - ``preserves a mid-flight re-toggle when the original mutation
    fails`` (asserts a user re-toggle survives the originating
    mutation's failure)

R4 — ``flushPendingChanges`` now invalidates the affected queries
inline on success, instead of relying on the caller's
``refreshAllModelInputs`` for the load-bearing invalidation. The
caller's refresh remains as an additive per-node template refresh.

Test infra: moved toggle-queue tests from
``useProviderConfiguration.test.tsx`` to a dedicated
``useModelToggleQueue.test.tsx`` that exercises the extracted hook
directly. Debounce mock changed from synchronous pass-through to
explicit ``runDebounced()`` so individual tests can choose whether to
exercise the debounced path or the awaitable ``flushPendingChanges``
path.

95/95 tests pass (87 prior + new R3 coverage + R4 success-path
invalidation).
2026-05-13 14:17:31 -07:00
b54bdf318d fix: update security dependencies (#13053)
* chore: update security dependencies

- Update brace-expansion to ^5.0.5 in docs
- Update picomatch to ^4.0.4 in docs
- Update ip-address to ^10.1.1 in frontend
- Update GitPython to >=3.1.48 in backend
- Add protobuf constraint >=6.33.6,<7.0.0 in backend

* chore: address additional CVEs and add security documentation

- Update lodash from deprecated 4.18.0 to 4.17.21
- Add docs/SECURITY_OVERRIDES.md documenting all CVEs
- Revert mem0ai 2.x upgrade due to compatibility issues

* fix: update dependencies to address CVE vulnerabilities

- Update langchain-core to >=1.3.3 (fixes CVE-2026-44843)
- Update GitPython to >=3.1.50 (partially fixes CVE-2026-44243, CVE-2026-44244, GHSA-mv93-w799-cj2w)
- Update pyarrow constraint to >=23.0.1,<24.0.0 (fixes CVE-2026-25087)
- Add override-dependencies for transitive packages:
  - lxml >=6.1.0 (fixes CVE-2026-41066)
  - mako >=1.3.12 (fixes CVE-2026-44307)
  - urllib3 >=2.7.0 (fixes CVE-2026-44431, CVE-2026-44432)
  - python-liquid >=2.2.0 (fixes CVE-2026-45017)

Total: 9 CVEs addressed
Smoke tests: All imports successful, no breaking changes detected

---------

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
2026-05-12 13:09:53 -04:00
6993a19bbe feat: Add SSRF protection with DNS rebinding prevention (#13016)
* feat: Add SSRF protection with DNS rebinding prevention

- Implement DNS pinning to prevent DNS rebinding attacks
- Enable SSRF protection by default (ssrf_protection_enabled = True)
- Add validate_and_resolve_url() function for DNS pinning
- Create SSRFProtectedTransport for custom HTTP transport
- Add comprehensive test suite for DNS rebinding protection
- Change from warn_only=True to warn_only=False for enforcement

This fixes a HIGH severity SSRF vulnerability (CVSS 8.6) that could allow
attackers to bypass SSRF protection using DNS rebinding attacks to access:
- Internal services and private networks
- Cloud metadata endpoints (AWS, GCP, Azure)
- Localhost services

The DNS pinning implementation ensures that the IP address validated during
security checks is the same IP used for the actual HTTP request, eliminating
the TOCTOU (Time-of-Check to Time-of-Use) vulnerability.

Changes:
- src/lfx/src/lfx/components/data_source/api_request.py: Integrate DNS pinning
- src/lfx/src/lfx/utils/ssrf_protection.py: Add validate_and_resolve_url()
- src/lfx/src/lfx/utils/ssrf_transport.py: Custom transport with DNS pinning
- src/lfx/src/lfx/services/settings/base.py: Enable SSRF protection by default
- src/backend/tests/unit/components/data_source/test_dns_rebinding.py: Test suite

Tested and verified working in GUI with DNS pinning logs visible.

* fix(security): implement network-level DNS pinning for SSRF protection with HTTPS support

This commit implements proper DNS rebinding protection that works with both HTTP and HTTPS by using network-level DNS pinning instead of URL rewriting.

## Changes

### Security Fixes
- **ssrf_protection.py**: Fixed critical vulnerability where IP validation returned early on first allowlisted IP, skipping validation of remaining IPs. Now validates ALL resolved IPs before making decisions.
- Blocks hostname if ANY resolved IP is blocked (even if others are allowlisted)
- Supports partial allowlisting (uses only allowlisted IPs for DNS pinning)
- Updated documentation to reflect that SSRF protection is now enabled by default
- Changed warn_only default from True to False for stricter security

### DNS Pinning Implementation
- **ssrf_transport.py**: Created DNSPinningNetworkBackend class that implements network-level DNS pinning
  - Extends httpcore.AsyncNetworkBackend to intercept TCP connections
  - Connects to pinned IP at network layer while preserving hostname for TLS
  - Works with both HTTP and HTTPS (fixes HTTPS regression from URL rewriting approach)
  - Properly handles TLS SNI and certificate verification

### Testing
- **test_dns_rebinding.py**: Updated all DNS rebinding tests to verify network-level behavior
  - Tests now patch AutoBackend.connect_tcp to capture actual IP connections
  - Verifies DNS pinning prevents rebinding attacks
  - Verifies hostname preservation for TLS
  - Tests IPv6 support
  - All 7 tests passing

## Technical Details

The previous URL rewriting approach (replacing hostname with IP in URL) broke HTTPS because:
1. TLS certificate is issued for hostname, not IP address
2. Certificate verification fails when connecting to IP
3. This was a regression - HTTPS worked before but was vulnerable

The new network-level approach:
1. Resolves DNS during validation and pins IPs
2. Uses custom AsyncNetworkBackend to intercept TCP connections
3. Connects to pinned IP at network layer
4. Preserves original hostname for TLS SNI and certificate verification
5. Works transparently with both HTTP and HTTPS

## Function Clarification

Two validation functions exist for different purposes:
- validate_url_for_ssrf(): Simple validation for URL component (no HTTP requests)
- validate_and_resolve_url(): Validation + DNS pinning for API Request component (makes HTTP requests)

Fixes DNS rebinding vulnerability while maintaining HTTPS compatibility.

* fix(security): support multiple IPs for dual-stack and load-balanced hosts

This commit fixes DNS pinning to properly handle hosts that resolve to multiple
IP addresses (dual-stack IPv4/IPv6, load balancing, etc.).

## Changes

### DNS Pinning Enhancement
- **ssrf_transport.py**: Updated to accept and use list of validated IPs
  - Changed pinned_ips from dict[str, str] to dict[str, list[str]]
  - DNSPinningNetworkBackend now tries IPs in order with fallback
  - Supports dual-stack (IPv4+IPv6) and load-balanced hosts
  - Falls back to next IP if connection fails

- **api_request.py**: Pass all validated IPs instead of just first one
  - Changed from validated_ips[0] to validated_ips
  - Enables proper failover for unreachable IPs

### Testing
- **test_dns_rebinding.py**: Added test_dns_pinning_with_multiple_ips_fallback
  - Verifies system tries multiple IPs when first fails
  - Tests dual-stack scenario (IPv4 fails, IPv6 succeeds)
  - Confirms IPs are tried in order
  - All 8 tests passing

## Technical Details

**Previous behavior:**
- Only used first validated IP (validated_ips[0])
- Failed if that single IP was unreachable
- Broke dual-stack and load-balanced hosts

**New behavior:**
- Accepts full list of validated IPs
- Tries each IP in order until one succeeds
- Properly supports:
  - Dual-stack hosts (IPv4 + IPv6)
  - Load-balanced hosts (multiple IPs)
  - Failover scenarios

This maintains security (all IPs validated during SSRF check) while improving
reliability and compatibility with modern networking configurations.

* fix: improve SSRF protection with DNS pinning and fix resource leak

- Implement network-level DNS pinning to prevent DNS rebinding attacks
- Fix resource leak in SSRFProtectedTransport by not calling super().__init__()
- Simplify error messages in SSRF protection (remove verbose explanations)
- Restore warn_only parameter in validate_url_for_ssrf() for backward compatibility
- Remove warn_only from validate_and_resolve_url() (not needed in API Request)
- Switch from private AutoBackend to public httpcore.AnyIOBackend() API
- Add noqa comments for unavoidable FBT and B008 warnings (matching parent class signature)
- Support dual-stack (IPv4/IPv6) and load-balanced hosts with multiple IPs
- Move imports to top of file for better code organization

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* test: fix SSRF protection test mocks to use validate_and_resolve_url

- Updated test mocks from validate_url_for_ssrf to validate_and_resolve_url
- Fixed test_ssrf_protection_disabled_by_default to explicitly disable protection
- All 12 SSRF protection tests now passing

* fix: read SSRF allowlist directly from environment for test compatibility

- Modified get_allowed_hosts() to read from os.getenv() first
- Fixes test isolation issue where settings service cached old values
- Ensures patch.dict() in tests properly overrides allowlist
- Maintains backward compatibility with settings service fallback

* test: fix test_ssrf_protection_enforcement_mode to properly mock validation

The test was failing because it wasn't mocking validate_and_resolve_url,
so the actual SSRF protection wasn't being triggered. Updated the test to:
- Mock validate_and_resolve_url to raise SSRFProtectionError
- Follow the same pattern as other SSRF protection tests
- Properly test that API Request component enforces blocking (no warn-only mode)

* refactor: rewrite SSRF protection tests to test real implementation

BREAKING CHANGE: Completely rewrote SSRF protection tests to properly test
actual security behavior instead of mocking core functions.

Changes:
- Removed all mocks of validate_and_resolve_url() - tests now verify real SSRF blocking
- Added tests that verify DNS pinning actually prevents rebinding attacks
- Test real blocking of private IPs (127.0.0.1, 192.168.x.x, 10.x.x.x, 172.16.x.x)
- Test real blocking of cloud metadata endpoints (169.254.169.254)
- Verify allowlist functionality with actual hostnames, IPs, and CIDR ranges
- Test that custom DNS pinning transport is used when protection is enabled
- Test that normal httpx client is used when protection is disabled
- Fixed environment variable caching in is_ssrf_protection_enabled()

Why this matters:
The old tests were mocking validate_and_resolve_url(), which meant they weren't
actually testing if SSRF protection works. They were just testing error handling.
Real SSRF vulnerabilities could have slipped through.

The new tests:
1. Let the real SSRF protection code run
2. Verify actual private IPs are blocked
3. Verify public URLs are allowed
4. Verify allowlist bypasses work correctly
5. Verify DNS pinning transport is actually used

All 41 tests pass (37 passed, 4 skipped for version checks).

---------

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-05-09 18:58:15 -04:00
276d16b2be chore(frontend): remove stale Dockerfile and start-nginx script (#12795)
These files were superseded by docker/frontend/ in Dec 2024 but left in
place. They still use the pre-openshift sed -i entrypoint that breaks
under readOnlyRootFilesystem, so any local build from this Dockerfile
produces a broken image. Nothing in CI, Makefile, or build tooling
references them.
2026-04-27 19:07:16 +00:00
ea3eae8b9e chore: update deps (#12951)
* chore: update deps

update deps

* chore: update uv.lock
2026-05-01 16:20:53 +00:00
cb06a666d0 fix(security): reject symlinks/hardlinks in BaseFileComponent TAR extraction (GHSA-ccv6-r384-xp75) (#12945)
`BaseFileComponent._unpack_bundle._safe_extract_tar` accepted any TAR member
type and only checked that `output_dir / member.name` did not escape the
extract dir. That check was performed before extraction, so a symlink whose
*target* was an absolute path (or `../` escape) was extracted untouched.
Once on disk the link was iterated by `temp_dir_path.iterdir()` and handed
to `process_files()`, whose concrete implementations (FileComponent,
DoclingInline/Remote, NvidiaIngest, VideoFile, Unstructured) call
`path.read_bytes()` and follow the link to read arbitrary host files.

The reporter's exploit chain leaks `~/.langflow/secret_key`, forges a JWT
for an admin user, and then runs arbitrary code through the Python
interpreter node, achieving RCE.

Python's `tarfile` only defaults to the safe `data` filter on Python 3.14,
which langflow's `requires-python = ">=3.10,<3.14"` excludes — so every
supported interpreter was vulnerable.

Fix:
- `_safe_extract_tar` now rejects symbolic-link, hard-link, FIFO, and
  device-node members with a `ValueError` and only extracts regular files
  and directories.
- `_unpack_and_collect_files` skips any `is_symlink()` entries from the
  extracted bundle directory and from recursive directory walks as
  defense-in-depth in case a future bundle format slips a link through.
- New `tests/unit/base/data/test_base_file_unpack.py` covers symlink (abs
  + relative escape), hardlink, FIFO rejection, benign tar/zip extraction,
  the post-extraction symlink filter, and an end-to-end repro mirroring
  the advisory PoC (real filesystem symlink → tarfile.add).

Refs: https://github.com/langflow-ai/langflow/security/advisories/GHSA-ccv6-r384-xp75
2026-04-30 17:22:27 +00:00
dce21ff925 ref: flip wxo ff (#12924)
* revert wxo deploy ffj

* skip deployments telemetry test when flag is off
2026-04-30 16:08:28 +00:00