|
31 | 31 | format_exception_message, |
32 | 32 | get_top_level_vertices, |
33 | 33 | parse_exception, |
| 34 | + scope_session_to_namespace, |
34 | 35 | verify_public_flow_and_get_user, |
35 | 36 | ) |
36 | 37 | from langflow.api.v1.schemas import ( |
@@ -661,6 +662,9 @@ async def build_public_tmp( |
661 | 662 | - The 'data' parameter is NOT accepted to prevent flow definition tampering |
662 | 663 | - Public flows must execute the stored flow definition only |
663 | 664 | - The flow definition is always loaded from the database |
| 665 | + - Caller-supplied 'inputs.session' is namespaced under the (client_id, |
| 666 | + flow_id) virtual flow ID so an unauthenticated caller cannot address a |
| 667 | + session that lives outside its own namespace (CVE-2026-33017) |
664 | 668 |
|
665 | 669 | The endpoint: |
666 | 670 | 1. Verifies the requested flow is marked as public in the database |
@@ -703,6 +707,12 @@ async def build_public_tmp( |
703 | 707 | authenticated_user_id=authenticated_user_id, |
704 | 708 | ) |
705 | 709 |
|
| 710 | + # Defends CVE-2026-33017: scope caller session into the (client_id, flow_id) namespace. |
| 711 | + if inputs is not None and inputs.session is not None: |
| 712 | + scoped_session = scope_session_to_namespace(inputs.session, str(new_flow_id)) |
| 713 | + if scoped_session != inputs.session: |
| 714 | + inputs = inputs.model_copy(update={"session": scoped_session}) |
| 715 | + |
706 | 716 | # Validate the stored flow data after the public-access boundary. |
707 | 717 | # Public flows never accept client-supplied data. |
708 | 718 | async with session_scope() as session: |
|
0 commit comments