Langflow Input and Schema Validation Mechanisms: A Complete Technical Guide

Langflow employs a three-layered validation architecture combining FastAPI request parsing, Pydantic schema enforcement, and custom business-logic validators to secure API requests against malformed data, injection attacks, and SSRF vulnerabilities.

The langflow-ai/langflow repository implements a defense-in-depth strategy for API request validation that spans from HTTP request parsing through to execution-time safety checks. This layered approach ensures that every flow execution request, code snippet, and external URL is sanitized before reaching the graph execution engine.

FastAPI Request Parsing Layer

Every public endpoint in Langflow is mounted through FastAPI's APIRouter, which provides the first line of defense against malformed JSON payloads. The validation-specific routes are defined in src/backend/base/langflow/api/v1/validate.py, where the router prefix isolates validation logic:

router = APIRouter(prefix="/validate", tags=["Validate"])

When a client sends a request to endpoints like /api/v1/flows/{flow_id}/run, FastAPI automatically deserializes the JSON body into Pydantic models such as SimplifiedAPIRequest. If the incoming JSON cannot be parsed into the expected structure, FastAPI returns a 422 Unprocessable Entity error before any application code executes, preventing invalid data from reaching business logic.

Pydantic Schema Enforcement

Once parsing succeeds, Pydantic models enforce type constraints, field validations, and custom preprocessing through the field_validator decorator pattern.

Core Request Models

The SimplifiedAPIRequest class in src/backend/base/langflow/api/v1/schemas.py serves as the primary schema for flow execution requests. It uses Pydantic V2 syntax to declare strict typing and default values:

class SimplifiedAPIRequest(BaseModel):
    input_value: str | None = Field(default=None, description="The input value")
    input_type: InputType | None = Field(default="chat", description="The input type")
    output_type: OutputType | None = Field(default="chat", description="The output type")
    # Additional fields...

Similarly, the FrontendNodeRequest model in src/backend/base/langflow/api/v1/base.py handles component definitions, ensuring that optional fields like imports maintain a consistent error structure even when omitted.

Field Validators

Pydantic validators run after type coercion but before the request reaches endpoint logic. For example, the FrontendNodeRequest model guarantees that import validation errors are always accessible:

@field_validator("imports")
@classmethod
def validate_imports(cls, v):
    return v or {"errors": []}

These validators enforce constraints like non-empty strings, allowed enum values, and custom preprocessing such as URL trimming, ensuring downstream code receives predictable data structures.

Custom Business-Logic Validation

After Pydantic validation completes, Langflow applies domain-specific validation rules through dedicated utility functions that protect against logical conflicts and security threats.

Input and Tweaks Validation

The validate_input_and_tweaks function in src/backend/base/langflow/api/v1/endpoints.py prevents ambiguous execution paths by detecting conflicts between top-level input values and component-specific tweaks:

def validate_input_and_tweaks(input_request: SimplifiedAPIRequest) -> None:
    if not input_request.tweaks:
        return
    for key, value in input_request.tweaks.items():
        # Detects conflicts between input_value and tweak payloads

This routine raises InvalidChatInputError if a user attempts to send both a raw input_value and a tweak targeting the same component, ensuring deterministic flow execution.

Code Validation

For custom component code, the validate_code function in src/lfx/src/lfx/custom/validate.py performs static analysis using Python's ast module:

  1. Verifies syntax is well-formed
  2. Extracts import statements
  3. Locates a callable named run (or the first function) and verifies its signature

If validation fails, the function returns a structured dictionary with imports and function keys containing error details, which the API wraps in a CodeValidationResponse.

Prompt Template Validation

Prompt validation occurs through process_prompt_template in src/lfx/src/lfx/base/prompts/api_utils.py. This utility parses Mustache and Jinja2 syntax to extract variable requirements:

input_variables = process_prompt_template(
    template=prompt_request.template,
    name=prompt_request.name,
    custom_fields=prompt_request.frontend_node.custom_fields,
    frontend_node_template=prompt_request.frontend_node.template,
    is_mustache=prompt_request.mustache,
)

The function returns a list of variable names that must be supplied by the frontend, preventing runtime template errors during flow execution.

SSRF Protection

Components that perform external HTTP requests invoke validate_url_for_ssrf from src/lfx/src/lfx/utils/ssrf_protection.py to block Server-Side Request Forgery attacks:

validate_url_for_ssrf(url, warn_only=False)

This function validates hostnames against safety patterns and blocks internal network addresses (e.g., 127.0.0.1, 169.254.169.254). If an unsafe URL is detected, it raises SSRFProtectionError, which components catch and surface as API errors.

Practical Implementation Examples

You can invoke Langflow's validation utilities directly in your own applications to ensure consistency with the platform's security model.

Validate a user-supplied Python snippet:

from lfx.custom.validate import validate_code

code = """
import requests

def run(input):
    return {"output": input}
"""

result = validate_code(code)
print(result)  # {'imports': {'errors': []}, 'function': {'errors': []}}

Extract variables from a Mustache template:

from lfx.base.prompts.api_utils import process_prompt_template

prompt = "Hello {{ name }}, today is {{ day }}."
variables = process_prompt_template(
    template=prompt,
    name="greeting",
    custom_fields=None,
    frontend_node_template=None,
    is_mustache=True,
)

print(variables)  # ['name', 'day']

Guard against SSRF vulnerabilities:

from lfx.utils.ssrf_protection import validate_url_for_ssrf, SSRFProtectionError

url = "http://169.254.169.254/metadata"
try:
    validate_url_for_ssrf(url, warn_only=False)
except SSRFProtectionError as exc:
    print(f"Blocked URL: {exc}")

Validate a flow execution payload:

from langflow.api.v1.schemas import SimplifiedAPIRequest
from langflow.api.v1.endpoints import validate_input_and_tweaks

payload = SimplifiedAPIRequest(
    input_value="Hello",
    input_type="chat",
    tweaks={"ChatInput": {"input_value": "Hello"}}
)

# Raises InvalidChatInputError due to conflicting input methods

validate_input_and_tweaks(payload)

Summary

Langflow's input and schema validation mechanisms operate through three coordinated layers:

  • FastAPI parsing handles JSON deserialization and returns 422 errors for malformed requests before application logic executes
  • Pydantic schemas enforce type safety and field constraints through models like SimplifiedAPIRequest and custom field_validator decorators
  • Business-logic validators provide domain-specific security checks including input/tweak conflict detection, Python code static analysis, template variable extraction, and SSRF URL filtering

This architecture ensures that malformed data, injection attempts, and unsafe external requests are intercepted before reaching the graph execution engine.

Frequently Asked Questions

How does Langflow prevent SSRF attacks in API components?

Langflow prevents SSRF attacks through the validate_url_for_ssrf function in src/lfx/src/lfx/utils/ssrf_protection.py. This utility checks URLs against a whitelist of safe patterns and blocks internal IP addresses including 127.0.0.1 and cloud metadata endpoints like 169.254.169.254. When an unsafe URL is detected, the function raises SSRFProtectionError, which API components catch and convert into user-facing error responses.

What happens if I send conflicting input values and tweaks to a flow endpoint?

If you send both a top-level input_value and a tweak targeting the same component (e.g., ChatInput), the validate_input_and_tweaks function in src/backend/base/langflow/api/v1/endpoints.py raises InvalidChatInputError. This validation ensures deterministic execution by preventing ambiguous input paths where the system cannot determine which value should take precedence.

Can I use Langflow's code validation outside the API context?

Yes, you can import validate_code from src/lfx/src/lfx/custom/validate.py to validate Python code snippets in any Python environment. The function uses the ast module to parse syntax, extract imports, and verify that a run function exists with the correct signature, returning a structured error report that matches the API's validation responses.

Which Pydantic models handle the main flow execution requests?

The primary model for flow execution requests is SimplifiedAPIRequest defined in src/backend/base/langflow/api/v1/schemas.py. This model validates fields including input_value, input_type, output_type, and tweaks using Pydantic V2's field_validator decorators. For component-specific requests, FrontendNodeRequest in src/backend/base/langflow/api/v1/base.py handles validation of node configurations and imports.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →