@@ -176,6 +176,41 @@ pub struct RagFileMetadataEntry {
176176 pub filename : String ,
177177}
178178
179+ // ---------------------------------------------------------------------------
180+ // Typed filter structs for RAG passthrough (prevents mass assignment)
181+ // ---------------------------------------------------------------------------
182+
183+ /// Allowed fields for POST /v1/vector_stores/{id} (modify).
184+ #[ derive( Debug , Serialize , Deserialize ) ]
185+ struct ModifyVectorStoreFilter {
186+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
187+ name : Option < String > ,
188+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
189+ expires_after : Option < Value > ,
190+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
191+ metadata : Option < HashMap < String , Value > > ,
192+ }
193+
194+ /// Allowed fields for POST /v1/vector_stores/{id}/search.
195+ #[ derive( Debug , Serialize , Deserialize ) ]
196+ struct SearchVectorStoreFilter {
197+ query : Value ,
198+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
199+ max_num_results : Option < u32 > ,
200+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
201+ filters : Option < Value > ,
202+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
203+ ranking_options : Option < Value > ,
204+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
205+ rewrite_query : Option < bool > ,
206+ }
207+
208+ /// Allowed fields for POST /v1/vector_stores/{id}/files/{file_id} (update attributes).
209+ #[ derive( Debug , Serialize , Deserialize ) ]
210+ struct UpdateFileAttributesFilter {
211+ attributes : HashMap < String , Value > ,
212+ }
213+
179214// ---------------------------------------------------------------------------
180215// Service Error
181216// ---------------------------------------------------------------------------
@@ -530,9 +565,15 @@ impl VectorStoreServiceTrait for VectorStoreServiceImpl {
530565 ) -> Result < Value , VectorStoreServiceError > {
531566 self . verify_vs ( vs_uuid, workspace_id) . await ?;
532567
568+ // Filter to allowed fields only (prevents mass assignment)
569+ let typed: ModifyVectorStoreFilter = serde_json:: from_value ( body)
570+ . map_err ( |e| VectorStoreServiceError :: InvalidParams ( e. to_string ( ) ) ) ?;
571+ let filtered_body = serde_json:: to_value ( & typed)
572+ . map_err ( |e| VectorStoreServiceError :: InvalidParams ( e. to_string ( ) ) ) ?;
573+
533574 let mut response = self
534575 . rag
535- . update_vector_store ( & vs_uuid. to_string ( ) , body )
576+ . update_vector_store ( & vs_uuid. to_string ( ) , filtered_body )
536577 . await ?;
537578 add_id_prefixes ( & mut response) ;
538579 Ok ( response)
@@ -563,9 +604,15 @@ impl VectorStoreServiceTrait for VectorStoreServiceImpl {
563604 ) -> Result < Value , VectorStoreServiceError > {
564605 self . verify_vs ( vs_uuid, workspace_id) . await ?;
565606
607+ // Filter to allowed fields only (prevents mass assignment)
608+ let typed: SearchVectorStoreFilter = serde_json:: from_value ( body)
609+ . map_err ( |e| VectorStoreServiceError :: InvalidParams ( e. to_string ( ) ) ) ?;
610+ let filtered_body = serde_json:: to_value ( & typed)
611+ . map_err ( |e| VectorStoreServiceError :: InvalidParams ( e. to_string ( ) ) ) ?;
612+
566613 let mut response = self
567614 . rag
568- . search_vector_store ( & vs_uuid. to_string ( ) , body )
615+ . search_vector_store ( & vs_uuid. to_string ( ) , filtered_body )
569616 . await ?;
570617 add_id_prefixes ( & mut response) ;
571618 Ok ( response)
@@ -642,9 +689,15 @@ impl VectorStoreServiceTrait for VectorStoreServiceImpl {
642689 self . verify_vs ( vs_uuid, workspace_id) . await ?;
643690 self . verify_file ( file_uuid, workspace_id) . await ?;
644691
692+ // Filter to allowed fields only (prevents mass assignment)
693+ let typed: UpdateFileAttributesFilter = serde_json:: from_value ( body)
694+ . map_err ( |e| VectorStoreServiceError :: InvalidParams ( e. to_string ( ) ) ) ?;
695+ let filtered_body = serde_json:: to_value ( & typed)
696+ . map_err ( |e| VectorStoreServiceError :: InvalidParams ( e. to_string ( ) ) ) ?;
697+
645698 let mut response = self
646699 . rag
647- . update_vs_file ( & vs_uuid. to_string ( ) , & file_uuid. to_string ( ) , body )
700+ . update_vs_file ( & vs_uuid. to_string ( ) , & file_uuid. to_string ( ) , filtered_body )
648701 . await ?;
649702 add_id_prefixes ( & mut response) ;
650703 Ok ( response)
@@ -684,6 +737,9 @@ impl VectorStoreServiceTrait for VectorStoreServiceImpl {
684737 . map_err ( |e| VectorStoreServiceError :: InvalidParams ( e. to_string ( ) ) ) ?;
685738
686739 if let Some ( obj) = rag_body. as_object_mut ( ) {
740+ // Remove unverified files field — only verified file_ids should reach RAG
741+ obj. remove ( "files" ) ;
742+
687743 // Replace file_ids with raw UUIDs
688744 let uuid_strings: Vec < Value > = file_uuids
689745 . iter ( )
0 commit comments