The security invariant

A model’s output is untrusted input; never route it straight into an interpreter.

01 / The boundary

The caller steers the model, and the model wrote the code.

The Smart Transform component asks a language model to write a small lambda from a user instruction, then runs that lambda to filter data. Because the caller controls the instruction, they influence what the model returns. That turns the model’s output into an untrusted channel: the text about to be executed inherits the caller’s intent, not the developer’s.

TraceMint reviewed the reviewed source snapshot at Langflow 1.7.1. The generated text passed a format-only check and then went to eval, so a prompt could drive the model to emit a lambda whose body performed arbitrary operations—a prompt-injection path to remote code execution.

02 / Execution path

From instruction to model text to eval.

The component built a prompt from the instruction, called the model, and kept the reply as working text. A regular expression pulled a lambda expression out of that free-form reply. The only gate then checked that the text began with the word lambda and contained a colon—a shape assertion, not a safety one—before the string was handed to eval.

A lambda body that constructs and calls dangerous operations satisfies that same shape while doing something entirely different. Because eval executed with full builtins, the generated expression could reach imports and process operations. The consequential fact is not the model’s cleverness but the direct path from its output to the interpreter.

The model output crosses into code
Before the fix
  1. Instruction to the model

    The caller shapes the request.

  2. Extract a lambda

    A regex pulls a lambda from the reply.

  3. Format check, then eval

    Shape is checked; the string is executed.

After the fix
  1. Instruction to the model

    The same request path.

  2. Screen for escape gadgets

    An AST check rejects unsafe constructs.

  3. Evaluate with safe builtins

    Dangerous names are unreachable.

Conceptual control flow reconstructed from the upstream source. It is not a captured request or a TraceMint execution trace.

03 / Source & fix

Screen the generated code and curate the builtins.

The later upstream change screens the generated lambda for escape gadgets before evaluating it, and evaluates it with a curated builtins mapping so names such as import, open, eval and exec are unreachable. The upstream comment describes this as defense-in-depth rather than a guaranteed sandbox. It also adds a deployment setting to block code-interpreter components where tenants should not author executable ones.

The excerpts contrast the reviewed 1.7.1 revision with the later hardening. The public commit establishes the code change; this note does not claim a causal link between the report and that change.

Before · model output taken backSource
response = await llm.ainvoke(prompt)response_text = response.content if hasattr(response, "content") else str(response)
lambda_filter.py47ce5bf2
Before · format-only validationSource
return lambda_text.strip().startswith("lambda") and ":" in lambda_text
lambda_filter.py47ce5bf2
Before · the eval sinkSource
fn: Callable[[Any], Any] = eval(lambda_text)  # noqa: S307
lambda_filter.py47ce5bf2
After · screen for unsafe codeSource
validate_code_safety(lambda_text)
lambda_filter.py1641b28f
After · evaluate with safe builtinsSource
return eval(lambda_text, {"__builtins__": safe_builtins()})  # noqa: S307
lambda_filter.py1641b28f

Selected upstream lines; indentation normalized. Links include surrounding code at immutable revisions.

04 / Impact & conditions

Execution in the Langflow process.

In the reporter-supplied local reproduction against 1.7.1, an instruction that steered the model toward an import-and-execute lambda passed the format check and reached eval, running an attacker-chosen command in the Langflow process. Practical exposure depended on who could add or run that component and on the deployment’s tenancy model. TraceMint first reported this in December 2025.

A reachable component
The attacker can add or run the Smart Transform component.
A steered model reply
The instruction drives the model toward an executable lambda.
A tenancy-dependent blast radius
Multi-tenant deployments widen who is affected by the execution.
05 / Review & regression

Treat the model reply as an attacker-controlled string.

A regression review drives the component with instructions that request an import-and-execute lambda and confirms that a hardened build refuses to evaluate them. Read the reply as untrusted input and check that the safety screen and the curated builtins both apply before execution. The scenarios below are suggested review checks, not reported TraceMint test results.

Suggested regression checks
ScenarioExpected boundary
A benign filtering lambdaThe intended transform still runs.
A lambda that imports a moduleThe safety screen rejects the generated code.
A lambda that reaches a dangerous builtinThe curated builtins make the name unreachable.
Component access in multi-tenant modeThe deployment setting can block code-interpreter components.
06 / Lessons & limits

Put a real boundary between the model and the interpreter.

For reviewers, any feature that turns generated text into behavior needs a genuine safety boundary—an allowlist, an AST check, a restricted execution environment—between the model and the interpreter, plus a separate decision about who may reach that feature at all. A format check is not that boundary.

This study analyzes immutable Langflow source revisions and a later public commit. TraceMint’s reporter record dates the first report to December 2025; that reporter-supplied date and the public code change do not, on their own, establish that this submission exclusively identified or caused the upstream change.

Source record

Follow the evidence.

Public upstream records and immutable code revisions, reviewed 2026-09-22.

  1. Upstream corrective commit

    1641b28f · screen generated code and evaluate with curated builtins (#13530).

  2. Component at the reviewed revision

    Immutable revision · 47ce5bf2 · Langflow 1.7.1 · format-only check, then eval.

  3. Component after the hardening

    Safety screen and curated builtins before evaluation.

Brief code excerpts from langflow-ai/langflow. Upstream license: MIT License. All remediation described here is upstream work.

Separate the records

The submitted date and reproduction details come from the reporter record. Public verification is limited to immutable Langflow source and the later upstream hardening commit.

No private disclosure correspondence is presented as a public source. The reviewed revision shows the LLM-output-to-eval path and the later commit shows the hardening. TraceMint’s reporter record dates the first report to December 2025; that reporter-supplied date and the public code change do not, on their own, establish that this submission exclusively identified or caused the upstream change.

More credited contributions