{
  "parent_claim_id": "cve-2026-33017",
  "variant_id": "cve-2026-33017-variant-stored-public-custom-component-rce",
  "equivalence_verdict": "same_root_cause_same_sink",
  "confidence": "high",
  "parent_root_cause": "Unauthenticated remote code execution via the public flow build path: attacker-controlled custom-component `code` (in a flow definition) is exec()'d at graph-build time inside prepare_global_scope()/eval_custom_component_code (src/lfx/src/lfx/custom/validate.py) with no sandboxing.",
  "parent_sink": {
    "file_path": "src/lfx/src/lfx/custom/validate.py",
    "function": "prepare_global_scope (called from create_class)",
    "primitive": "exec(compiled_module, exec_globals) of attacker-controlled module-level statements (ast.Assign/AnnAssign/ClassDef/FunctionDef)"
  },
  "variant_root_cause": "Identical: the same unauthenticated public build path exec()'s a node's custom-component `code` at graph-build time. The only difference is the injection point for the malicious code: the parent supplies it in the request `data` body (closed by the v1.9.0 fix); the variant persists it in the DB via a PUBLIC flow and lets the public build load it from the DB.",
  "variant_sink": {
    "file_path": "src/lfx/src/lfx/custom/validate.py",
    "function": "prepare_global_scope (called from create_class via Graph.from_payload via build_graph_from_db)",
    "primitive": "exec(compiled_module, exec_globals) of attacker-controlled module-level statements"
  },
  "shared_call_chain": "POST /api/v1/build_public_tmp/{flow_id}/flow -> start_flow_build -> generate_flow_events -> create_graph -> (build_graph_from_data | build_graph_from_db) -> Graph.from_payload -> create_class -> prepare_global_scope -> exec()",
  "trust_boundary": "Unauthenticated remote (the public build endpoint requires only a client_id cookie; the flow-creation pre-step uses the AUTO_LOGIN superuser token with no credentials, identical to the parent repro's setup).",
  "difference_from_parent": {
    "injection_point": "parent: request body `data` field (FlowDataRequest) -> closed by v1.9.0 removing the parameter. variant: stored flow `data` in the database, written via POST /api/v1/flows/ -> NOT closed by v1.9.0.",
    "fix_coverage_gap": "v1.9.0 validate_flow_for_current_settings(flow.data) is a no-op under default allow_custom_components=true (src/lfx/src/lfx/services/settings/base.py:386), so the stored malicious custom component is not blocked.",
    "validated_on": "langflow 1.9.0 (the CVE's 'fixed' version) - bypass reproduces (exploit_status=200, proof written, uid=1000(user)).",
    "closed_by": "v1.10.1 follow-up commit 626365f088 (prepare_public_flow_build substitutes trusted server code / rejects unknown custom component types; allow_public_custom_components default false)."
  },
  "is_bypass": true,
  "bypass_of_version": "1.9.0 (CVE-2026-33017 stated fixed version)",
  "bypass_closed_in_version": "1.10.1",
  "evidence": {
    "vuln_1_9_0_result": "logs/vuln_variant/result_claimed_fixed_1.json (exploit_status=200, proof_exists=true, proof_content uid=1000(user)...RCE_CONFIRMED <token>)",
    "fixed_1_10_1_result": "logs/vuln_variant/result_followup_fixed_1.json (exploit_status=400, This flow cannot be executed., proof_exists=false)",
    "reproduction_script": "bundle/vuln_variant/reproduction_steps.sh"
  }
}
