22
33use super :: types:: ModelPreset ;
44
5+ /// Allowed models for Chutes provider (whitelist approach for security).
6+ /// Only these models can be used with the Chutes provider.
7+ pub const CHUTES_ALLOWED_MODELS : & [ & str ] = & [ "moonshotai/Kimi-K2.5-TEE" ] ;
8+
59/// Available model presets.
610pub const MODEL_PRESETS : & [ ModelPreset ] = & [
711 ModelPreset {
@@ -837,21 +841,41 @@ pub fn get_models_for_provider(provider: &str) -> Vec<&'static ModelPreset> {
837841/// Returns Ok(()) if valid, Err with message if invalid.
838842pub fn validate_chutes_model ( model : & str ) -> Result < ( ) , String > {
839843 let model = model. trim ( ) ;
844+
845+ // Check for empty model
846+ if model. is_empty ( ) {
847+ return Err ( "Model name cannot be empty for Chutes provider" . to_string ( ) ) ;
848+ }
849+
850+ // Check suffix (case-insensitive)
840851 if !model. to_uppercase ( ) . ends_with ( "-TEE" ) {
841852 return Err ( format ! (
842853 "Chutes provider only allows TEE models (models ending with '-TEE'). \
843- Model '{}' is not a TEE model. Available TEE models: moonshotai/Kimi-K2.5-TEE",
844- model
854+ Model '{}' is not a TEE model. Available TEE models: {}",
855+ model,
856+ CHUTES_ALLOWED_MODELS . join( ", " )
845857 ) ) ;
846858 }
859+
860+ // SECURITY: Also verify model is in the allowed whitelist
861+ if !CHUTES_ALLOWED_MODELS . iter ( ) . any ( |& allowed| allowed. eq_ignore_ascii_case ( model) ) {
862+ return Err ( format ! (
863+ "Model '{}' is not in the allowed Chutes models list. \
864+ Available models: {}",
865+ model,
866+ CHUTES_ALLOWED_MODELS . join( ", " )
867+ ) ) ;
868+ }
869+
847870 Ok ( ( ) )
848871}
849872
850873/// Checks if a provider restricts custom models.
851874/// Chutes only allows predefined TEE models, no custom models.
852875pub fn provider_allows_custom_models ( provider : & str ) -> bool {
853876 // Chutes does NOT allow custom models - only predefined TEE models
854- provider != "chutes"
877+ // Use case-insensitive comparison
878+ !provider. eq_ignore_ascii_case ( "chutes" )
855879}
856880
857881#[ cfg( test) ]
@@ -860,31 +884,52 @@ mod tests {
860884
861885 #[ test]
862886 fn test_validate_chutes_model_valid ( ) {
863- // Valid TEE models
887+ // Valid TEE models in whitelist
864888 assert ! ( validate_chutes_model( "moonshotai/Kimi-K2.5-TEE" ) . is_ok( ) ) ;
865- assert ! ( validate_chutes_model( "some-model-TEE" ) . is_ok( ) ) ;
866889 // Case insensitive
867- assert ! ( validate_chutes_model( "model -tee" ) . is_ok( ) ) ;
868- assert ! ( validate_chutes_model( "model-Tee " ) . is_ok( ) ) ;
890+ assert ! ( validate_chutes_model( "moonshotai/kimi-k2.5 -tee" ) . is_ok( ) ) ;
891+ assert ! ( validate_chutes_model( "MOONSHOTAI/KIMI-K2.5-TEE " ) . is_ok( ) ) ;
869892 // Whitespace handling
870- assert ! ( validate_chutes_model( " model -TEE " ) . is_ok( ) ) ;
893+ assert ! ( validate_chutes_model( " moonshotai/Kimi-K2.5 -TEE " ) . is_ok( ) ) ;
871894 }
872895
873896 #[ test]
874897 fn test_validate_chutes_model_invalid ( ) {
898+ // Not a TEE model
875899 assert ! ( validate_chutes_model( "gpt-4" ) . is_err( ) ) ;
876900 assert ! ( validate_chutes_model( "claude-3" ) . is_err( ) ) ;
901+
902+ // Has TEE suffix but NOT in whitelist
903+ assert ! ( validate_chutes_model( "fake-model-TEE" ) . is_err( ) ) ;
904+ assert ! ( validate_chutes_model( "some-model-TEE" ) . is_err( ) ) ;
905+
906+ // TEE in wrong position
877907 assert ! ( validate_chutes_model( "model-TEE-v2" ) . is_err( ) ) ;
878- assert ! ( validate_chutes_model( "" ) . is_err( ) ) ;
908+
909+ // Empty string
910+ let result = validate_chutes_model ( "" ) ;
911+ assert ! ( result. is_err( ) ) ;
912+ assert ! ( result. unwrap_err( ) . contains( "cannot be empty" ) ) ;
879913 }
880914
881915 #[ test]
882916 fn test_provider_allows_custom_models ( ) {
883- // Chutes does NOT allow custom models
917+ // Chutes does NOT allow custom models - case insensitive
884918 assert ! ( !provider_allows_custom_models( "chutes" ) ) ;
919+ assert ! ( !provider_allows_custom_models( "Chutes" ) ) ;
920+ assert ! ( !provider_allows_custom_models( "CHUTES" ) ) ;
921+
885922 // Other providers allow custom models
886923 assert ! ( provider_allows_custom_models( "cortex" ) ) ;
887924 assert ! ( provider_allows_custom_models( "openai" ) ) ;
888925 assert ! ( provider_allows_custom_models( "anthropic" ) ) ;
889926 }
927+
928+ #[ test]
929+ fn test_chutes_allowed_models_list ( ) {
930+ // Verify the whitelist contains expected model
931+ assert ! ( CHUTES_ALLOWED_MODELS . contains( & "moonshotai/Kimi-K2.5-TEE" ) ) ;
932+ // Whitelist should not be empty
933+ assert ! ( !CHUTES_ALLOWED_MODELS . is_empty( ) ) ;
934+ }
890935}
0 commit comments