CVE-2024-5181: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE-78)
value: A command injection vulnerability exists in the mudler/localai version 2.14.0. The vulnerability arises from the application's handling of the backend parameter in the configuration file, which is used in the name of the initialized process. An attacker can exploit this vulnerability by manipulating the path of the vulnerable binary file specified in the backend parameter, allowing the execution of arbitrary code on the system. This issue is due to improper neutralization of special elements used in an OS command, leading to potential full control over the affected system.
CWE description: The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
Published: 2024-06-26T03:15Z
Repository: https://github.com/mudler/localai
Language: Other
Files changed: .github/workflows/generate_grpc_cache.yaml, .github/workflows/image_build.yml, .github/workflows/release.yaml, .github/workflows/test-extra.yml, .github/workflows/test.yml, backend/python/autogptq/requirements.txt, backend/python/bark/requirements.txt, backend/python/common/template/requirements.txt, backend/python/coqui/requirements.txt, backend/python/diffusers/requirements.txt, backend/python/exllama/requirements.txt, backend/python/exllama2/requirements.txt, backend/python/mamba/requirements.txt, backend/python/openvoice/requirements-intel.txt, backend/python/openvoice/requirements.txt, backend/python/parler-tts/requirements.txt, backend/python/rerankers/requirements.txt, backend/python/sentencetransformers/requirements.txt, backend/python/transformers-musicgen/requirements.txt, backend/python/transformers/requirements.txt, backend/python/vall-e-x/requirements.txt, backend/python/vllm/requirements.txt, core/config/backend_config.go, core/config/backend_config_loader.go, core/config/backend_config_test.go, core/config/config_suite_test.go, core/config/config_test.go, pkg/model/process.go
Commit date: 2024-05-21 14:33:47 +0200
Commit message: dependencies(grpcio): bump to fix CI issues (#2362)

feat(grpcio): bump to fix CI issues

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Diff: diff --git a/.github/workflows/generate_grpc_cache.yaml b/.github/workflows/generate_grpc_cache.yaml
index b52a137c..3d80b967 100644
--- a/.github/workflows/generate_grpc_cache.yaml
+++ b/.github/workflows/generate_grpc_cache.yaml
@@ -82,11 +82,11 @@ jobs:
           # This means that even the MAKEFLAGS have to be an EXACT match.
           # If the build-args are not an EXACT match, it will result in a cache miss, which will require GRPC to be built from scratch.
           build-args: |
             GRPC_BASE_IMAGE=${{ matrix.grpc-base-image }}
             GRPC_MAKEFLAGS=--jobs=4 --output-sync=target
-            GRPC_VERSION=v1.63.0
+            GRPC_VERSION=v1.64.0
           context: .
           file: ./Dockerfile
           cache-to: type=gha,ignore-error=true
           cache-from: type=gha
           target: grpc
diff --git a/.github/workflows/image_build.yml b/.github/workflows/image_build.yml
index 4b5ebecd..2a4c4aed 100644
--- a/.github/workflows/image_build.yml
+++ b/.github/workflows/image_build.yml
@@ -216,11 +216,11 @@ jobs:
             FFMPEG=${{ inputs.ffmpeg }}
             IMAGE_TYPE=${{ inputs.image-type }}
             BASE_IMAGE=${{ inputs.base-image }}
             GRPC_BASE_IMAGE=${{ inputs.grpc-base-image || inputs.base-image }}
             GRPC_MAKEFLAGS=--jobs=4 --output-sync=target
-            GRPC_VERSION=v1.63.0
+            GRPC_VERSION=v1.64.0
             MAKEFLAGS=${{ inputs.makeflags }}
           context: .
           file: ./Dockerfile
           cache-from: type=gha
           platforms: ${{ inputs.platforms }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 8ff64a3f..bcd4b9da 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -3,11 +3,11 @@ name: Build and Release
 on:
 - push
 - pull_request
 
 env:
-  GRPC_VERSION: v1.63.0
+  GRPC_VERSION: v1.64.0
 
 permissions:
   contents: write
 
 concurrency:
diff --git a/.github/workflows/test-extra.yml b/.github/workflows/test-extra.yml
index b06812fd..0ec6ef9e 100644
--- a/.github/workflows/test-extra.yml
+++ b/.github/workflows/test-extra.yml
@@ -27,11 +27,11 @@ jobs:
           sudo apt-get install build-essential ffmpeg
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
           
       - name: Test transformers
         run: |
            make --jobs=5 --output-sync=target -C backend/python/transformers
            make --jobs=5 --output-sync=target -C backend/python/transformers test
@@ -49,11 +49,11 @@ jobs:
           sudo apt-get install build-essential ffmpeg
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
           
       - name: Test sentencetransformers
         run: |
            make --jobs=5 --output-sync=target -C backend/python/sentencetransformers
            make --jobs=5 --output-sync=target -C backend/python/sentencetransformers test
@@ -72,11 +72,11 @@ jobs:
           sudo apt-get install build-essential ffmpeg
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
 
       - name: Test rerankers
         run: |
            make --jobs=5 --output-sync=target -C backend/python/rerankers
            make --jobs=5 --output-sync=target -C backend/python/rerankers test
@@ -94,11 +94,11 @@ jobs:
           sudo apt-get install -y build-essential ffmpeg
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
       - name: Test diffusers
         run: |
           make --jobs=5 --output-sync=target -C backend/python/diffusers
           make --jobs=5 --output-sync=target -C backend/python/diffusers test
 
@@ -115,11 +115,11 @@ jobs:
           sudo apt-get install build-essential ffmpeg
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
 
       - name: Test parler-tts
         run: |
            make --jobs=5 --output-sync=target -C backend/python/parler-tts
            make --jobs=5 --output-sync=target -C backend/python/parler-tts test
@@ -137,11 +137,11 @@ jobs:
           sudo apt-get install build-essential ffmpeg
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
 
       - name: Test openvoice
         run: |
            make --jobs=5 --output-sync=target -C backend/python/openvoice
            make --jobs=5 --output-sync=target -C backend/python/openvoice test
@@ -159,11 +159,11 @@ jobs:
           sudo apt-get install build-essential ffmpeg
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
 
       - name: Test transformers-musicgen
         run: |
            make --jobs=5 --output-sync=target -C backend/python/transformers-musicgen
            make --jobs=5 --output-sync=target -C backend/python/transformers-musicgen test
@@ -183,11 +183,11 @@ jobs:
   #         sudo apt-get install build-essential ffmpeg
   #         # Install UV
   #         curl -LsSf https://astral.sh/uv/install.sh | sh
   #         sudo apt-get install -y ca-certificates cmake curl patch python3-pip
   #         sudo apt-get install -y libopencv-dev
-  #         pip install --user grpcio-tools==1.63.0
+  #         pip install --user grpcio-tools==1.64.0
 
   #     - name: Test petals
   #       run: |
   #          make --jobs=5 --output-sync=target -C backend/python/petals
   #          make --jobs=5 --output-sync=target -C backend/python/petals test
@@ -247,11 +247,11 @@ jobs:
   #         sudo apt-get install build-essential ffmpeg
   #         # Install UV
   #         curl -LsSf https://astral.sh/uv/install.sh | sh
   #         sudo apt-get install -y ca-certificates cmake curl patch python3-pip
   #         sudo apt-get install -y libopencv-dev
-  #         pip install --user grpcio-tools==1.63.0
+  #         pip install --user grpcio-tools==1.64.0
 
   #     - name: Test bark
   #       run: |
   #          make --jobs=5 --output-sync=target -C backend/python/bark
   #          make --jobs=5 --output-sync=target -C backend/python/bark test
@@ -272,11 +272,11 @@ jobs:
   #         sudo apt-get install build-essential ffmpeg
   #         # Install UV
   #         curl -LsSf https://astral.sh/uv/install.sh | sh
   #         sudo apt-get install -y ca-certificates cmake curl patch python3-pip
   #         sudo apt-get install -y libopencv-dev
-  #         pip install --user grpcio-tools==1.63.0
+  #         pip install --user grpcio-tools==1.64.0
   #     - name: Test vllm
   #       run: |
   #          make --jobs=5 --output-sync=target -C backend/python/vllm
   #          make --jobs=5 --output-sync=target -C backend/python/vllm test
   tests-vallex:
@@ -292,11 +292,11 @@ jobs:
           sudo apt-get install build-essential ffmpeg
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
           sudo apt-get install -y ca-certificates cmake curl patch python3-pip
           sudo apt-get install -y libopencv-dev
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
       - name: Test vall-e-x
         run: |
            make --jobs=5 --output-sync=target -C backend/python/vall-e-x
            make --jobs=5 --output-sync=target -C backend/python/vall-e-x test
 
@@ -312,10 +312,10 @@ jobs:
           sudo apt-get update
           sudo apt-get install build-essential ffmpeg
           sudo apt-get install -y ca-certificates cmake curl patch espeak espeak-ng python3-pip
           # Install UV
           curl -LsSf https://astral.sh/uv/install.sh | sh
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
       - name: Test coqui
         run: |
           make --jobs=5 --output-sync=target -C backend/python/coqui
           make --jobs=5 --output-sync=target -C backend/python/coqui test
\ No newline at end of file
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4d73f219..be704187 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -8,11 +8,11 @@ on:
       - master
     tags:
       - '*'
 
 env:
-  GRPC_VERSION: v1.63.0
+  GRPC_VERSION: v1.64.0
 
 concurrency:
   group: ci-tests-${{ github.head_ref || github.ref }}-${{ github.repository }}
   cancel-in-progress: true
 
@@ -211,11 +211,11 @@ jobs:
       - name: Display Go version
         run: go version
       - name: Dependencies
         run: |
           brew install protobuf grpc make protoc-gen-go protoc-gen-go-grpc
-          pip install --user grpcio-tools==1.63.0
+          pip install --user grpcio-tools==1.64.0
       - name: Test
         run: |
           export C_INCLUDE_PATH=/usr/local/include
           export CPLUS_INCLUDE_PATH=/usr/local/include
           # Used to run the newer GNUMake version from brew that supports --output-sync
diff --git a/backend/python/autogptq/requirements.txt b/backend/python/autogptq/requirements.txt
index 05dac8c8..7a18bfc0 100644
--- a/backend/python/autogptq/requirements.txt
+++ b/backend/python/autogptq/requirements.txt
@@ -1,7 +1,7 @@
 accelerate
 auto-gptq==0.7.1
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 torch
 certifi
 transformers
\ No newline at end of file
diff --git a/backend/python/bark/requirements.txt b/backend/python/bark/requirements.txt
index 2aec63f7..6680a8b5 100644
--- a/backend/python/bark/requirements.txt
+++ b/backend/python/bark/requirements.txt
@@ -1,6 +1,6 @@
 accelerate
 bark==0.1.5
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
 transformers
\ No newline at end of file
diff --git a/backend/python/common/template/requirements.txt b/backend/python/common/template/requirements.txt
index 8859595c..4a3bd2bc 100644
--- a/backend/python/common/template/requirements.txt
+++ b/backend/python/common/template/requirements.txt
@@ -1,2 +1,2 @@
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
\ No newline at end of file
diff --git a/backend/python/coqui/requirements.txt b/backend/python/coqui/requirements.txt
index b7c7faf3..24621f34 100644
--- a/backend/python/coqui/requirements.txt
+++ b/backend/python/coqui/requirements.txt
@@ -1,6 +1,6 @@
 accelerate
 TTS==0.22.0
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
 transformers
\ No newline at end of file
diff --git a/backend/python/diffusers/requirements.txt b/backend/python/diffusers/requirements.txt
index 84b34302..1c663adc 100644
--- a/backend/python/diffusers/requirements.txt
+++ b/backend/python/diffusers/requirements.txt
@@ -1,9 +1,9 @@
 accelerate
 compel
 diffusers
-grpcio==1.63.0
+grpcio==1.64.0
 opencv-python
 pillow
 protobuf
 torch
 transformers
diff --git a/backend/python/exllama/requirements.txt b/backend/python/exllama/requirements.txt
index 784e50b0..7a1d5464 100644
--- a/backend/python/exllama/requirements.txt
+++ b/backend/python/exllama/requirements.txt
@@ -1,6 +1,6 @@
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 torch
 transformers
 certifi
 setuptools
\ No newline at end of file
diff --git a/backend/python/exllama2/requirements.txt b/backend/python/exllama2/requirements.txt
index 25cd1e65..e9aa977f 100644
--- a/backend/python/exllama2/requirements.txt
+++ b/backend/python/exllama2/requirements.txt
@@ -1,7 +1,7 @@
 accelerate
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
 torch
 wheel
 setuptools
\ No newline at end of file
diff --git a/backend/python/mamba/requirements.txt b/backend/python/mamba/requirements.txt
index f8225c1c..8b089512 100644
--- a/backend/python/mamba/requirements.txt
+++ b/backend/python/mamba/requirements.txt
@@ -1,6 +1,6 @@
 causal-conv1d==1.2.0.post2
 mamba-ssm==1.2.0.post1
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
 transformers
\ No newline at end of file
diff --git a/backend/python/openvoice/requirements-intel.txt b/backend/python/openvoice/requirements-intel.txt
index 421615e9..ba299a57 100644
--- a/backend/python/openvoice/requirements-intel.txt
+++ b/backend/python/openvoice/requirements-intel.txt
@@ -1,10 +1,10 @@
 --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/xpu/us/
 intel-extension-for-pytorch
 torch
 optimum[openvino]
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 librosa==0.9.1
 faster-whisper==0.9.0
 pydub==0.25.1
 wavmark==0.0.3
diff --git a/backend/python/openvoice/requirements.txt b/backend/python/openvoice/requirements.txt
index c186bd5a..ac2e8dcd 100644
--- a/backend/python/openvoice/requirements.txt
+++ b/backend/python/openvoice/requirements.txt
@@ -1,6 +1,6 @@
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 librosa==0.9.1
 faster-whisper==0.9.0
 pydub==0.25.1
 wavmark==0.0.3
diff --git a/backend/python/parler-tts/requirements.txt b/backend/python/parler-tts/requirements.txt
index 31085e3d..ba30594f 100644
--- a/backend/python/parler-tts/requirements.txt
+++ b/backend/python/parler-tts/requirements.txt
@@ -1,7 +1,7 @@
 accelerate
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 torch
 git+https://github.com/huggingface/parler-tts.git@10016fb0300c0dc31a0fb70e26f3affee7b62f16
 certifi
 transformers
\ No newline at end of file
diff --git a/backend/python/rerankers/requirements.txt b/backend/python/rerankers/requirements.txt
index c4eac2f4..db861321 100644
--- a/backend/python/rerankers/requirements.txt
+++ b/backend/python/rerankers/requirements.txt
@@ -1,6 +1,6 @@
 accelerate
 rerankers[transformers]
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
 transformers
\ No newline at end of file
diff --git a/backend/python/sentencetransformers/requirements.txt b/backend/python/sentencetransformers/requirements.txt
index b00dc058..d3f4e1f3 100644
--- a/backend/python/sentencetransformers/requirements.txt
+++ b/backend/python/sentencetransformers/requirements.txt
@@ -1,6 +1,6 @@
 accelerate
 sentence-transformers==2.5.1
 transformers
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
\ No newline at end of file
diff --git a/backend/python/transformers-musicgen/requirements.txt b/backend/python/transformers-musicgen/requirements.txt
index 8f6d7be6..06588c5c 100644
--- a/backend/python/transformers-musicgen/requirements.txt
+++ b/backend/python/transformers-musicgen/requirements.txt
@@ -1,7 +1,7 @@
 accelerate
 transformers
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 torch
 scipy==1.13.0
 certifi
\ No newline at end of file
diff --git a/backend/python/transformers/requirements.txt b/backend/python/transformers/requirements.txt
index 57ceb96d..5f4f4687 100644
--- a/backend/python/transformers/requirements.txt
+++ b/backend/python/transformers/requirements.txt
@@ -1,6 +1,6 @@
 accelerate
 transformers
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 torch
 certifi
\ No newline at end of file
diff --git a/backend/python/vall-e-x/requirements.txt b/backend/python/vall-e-x/requirements.txt
index 075c6231..a2a720f2 100644
--- a/backend/python/vall-e-x/requirements.txt
+++ b/backend/python/vall-e-x/requirements.txt
@@ -1,4 +1,4 @@
 accelerate
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
\ No newline at end of file
diff --git a/backend/python/vllm/requirements.txt b/backend/python/vllm/requirements.txt
index 3de0b4e2..0da43c3a 100644
--- a/backend/python/vllm/requirements.txt
+++ b/backend/python/vllm/requirements.txt
@@ -1,7 +1,7 @@
 accelerate
 vllm
-grpcio==1.63.0
+grpcio==1.64.0
 protobuf
 certifi
 transformers
 setuptools
\ No newline at end of file
diff --git a/core/config/backend_config.go b/core/config/backend_config.go
index 6b9aa54e..99154c9a 100644
--- a/core/config/backend_config.go
+++ b/core/config/backend_config.go
@@ -1,9 +1,11 @@
 package config
 
 import (
 	"os"
+	"regexp"
+	"strings"
 
 	"github.com/go-skynet/LocalAI/core/schema"
 	"github.com/go-skynet/LocalAI/pkg/downloader"
 	"github.com/go-skynet/LocalAI/pkg/functions"
 	"github.com/go-skynet/LocalAI/pkg/utils"
@@ -354,5 +356,27 @@ func (cfg *BackendConfig) SetDefaults(opts ...ConfigLoaderOption) {
 
 	if debug {
 		cfg.Debug = &trueV
 	}
 }
+
+func (c *BackendConfig) Validate() bool {
+	// Simple validation to make sure the model can be correctly loaded
+	for _, n := range []string{c.Backend, c.Model} {
+		if strings.HasPrefix(n, string(os.PathSeparator)) ||
+			strings.Contains(n, "..") {
+			return false
+		}
+	}
+
+	if c.Name == "" {
+		return false
+	}
+
+	if c.Backend != "" {
+		// a regex that checks that is a string name with no special characters, except '-' and '_'
+		re := regexp.MustCompile(`^[a-zA-Z0-9-_]+$`)
+		return re.MatchString(c.Backend)
+	}
+
+	return true
+}
diff --git a/core/config/backend_config_loader.go b/core/config/backend_config_loader.go
index cf7238ce..ce02fc9a 100644
--- a/core/config/backend_config_loader.go
+++ b/core/config/backend_config_loader.go
@@ -141,11 +141,13 @@ func (cm *BackendConfigLoader) LoadBackendConfigFile(file string, opts ...Config
 	if err != nil {
 		return fmt.Errorf("cannot load config file: %w", err)
 	}
 
 	for _, cc := range c {
-		cm.configs[cc.Name] = *cc
+		if cc.Validate() {
+			cm.configs[cc.Name] = *cc
+		}
 	}
 	return nil
 }
 
 func (cl *BackendConfigLoader) LoadBackendConfig(file string, opts ...ConfigLoaderOption) error {
@@ -154,11 +156,16 @@ func (cl *BackendConfigLoader) LoadBackendConfig(file string, opts ...ConfigLoad
 	c, err := ReadBackendConfig(file, opts...)
 	if err != nil {
 		return fmt.Errorf("cannot read config file: %w", err)
 	}
 
-	cl.configs[c.Name] = *c
+	if c.Validate() {
+		cl.configs[c.Name] = *c
+	} else {
+		return fmt.Errorf("config is not valid")
+	}
+
 	return nil
 }
 
 func (cl *BackendConfigLoader) GetBackendConfig(m string) (BackendConfig, bool) {
 	cl.Lock()
@@ -295,11 +302,11 @@ func (cl *BackendConfigLoader) Preload(modelPath string) error {
 func (cm *BackendConfigLoader) LoadBackendConfigsFromPath(path string, opts ...ConfigLoaderOption) error {
 	cm.Lock()
 	defer cm.Unlock()
 	entries, err := os.ReadDir(path)
 	if err != nil {
-		return err
+		return fmt.Errorf("cannot read directory '%s': %w", path, err)
 	}
 	files := make([]fs.FileInfo, 0, len(entries))
 	for _, entry := range entries {
 		info, err := entry.Info()
 		if err != nil {
@@ -312,12 +319,18 @@ func (cm *BackendConfigLoader) LoadBackendConfigsFromPath(path string, opts ...C
 		if !strings.Contains(file.Name(), ".yaml") && !strings.Contains(file.Name(), ".yml") ||
 			strings.HasPrefix(file.Name(), ".") {
 			continue
 		}
 		c, err := ReadBackendConfig(filepath.Join(path, file.Name()), opts...)
-		if err == nil {
+		if err != nil {
+			log.Error().Err(err).Msgf("cannot read config file: %s", file.Name())
+			continue
+		}
+		if c.Validate() {
 			cm.configs[c.Name] = *c
+		} else {
+			log.Error().Err(err).Msgf("config is not valid")
 		}
 	}
 
 	return nil
 }
diff --git a/core/config/backend_config_test.go b/core/config/backend_config_test.go
new file mode 100644
index 00000000..4c1437e3
--- /dev/null
+++ b/core/config/backend_config_test.go
@@ -0,0 +1,65 @@
+package config_test
+
+import (
+	"io"
+	"net/http"
+	"os"
+
+	. "github.com/go-skynet/LocalAI/core/config"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+var _ = Describe("Test cases for config related functions", func() {
+	Context("Test Read configuration functions", func() {
+		It("Test Validate", func() {
+			tmp, err := os.CreateTemp("", "config.yaml")
+			Expect(err).To(BeNil())
+			defer os.Remove(tmp.Name())
+			_, err = tmp.WriteString(
+				`backend: "foo-bar"
+parameters:
+  model: "foo-bar"`)
+			Expect(err).ToNot(HaveOccurred())
+			config, err := ReadBackendConfig(tmp.Name())
+			Expect(err).To(BeNil())
+			Expect(config).ToNot(BeNil())
+			Expect(config.Validate()).To(BeFalse())
+		})
+		It("Test Validate", func() {
+			tmp, err := os.CreateTemp("", "config.yaml")
+			Expect(err).To(BeNil())
+			defer os.Remove(tmp.Name())
+			_, err = tmp.WriteString(
+				`name: bar-baz
+backend: "foo-bar"
+parameters:
+  model: "foo-bar"`)
+			Expect(err).ToNot(HaveOccurred())
+			config, err := ReadBackendConfig(tmp.Name())
+			Expect(err).To(BeNil())
+			Expect(config).ToNot(BeNil())
+			// two configs in config.yaml
+			Expect(config.Name).To(Equal("bar-baz"))
+			Expect(config.Validate()).To(BeTrue())
+
+			// download https://raw.githubusercontent.com/mudler/LocalAI/master/embedded/models/hermes-2-pro-mistral.yaml
+			httpClient := http.Client{}
+			resp, err := httpClient.Get("https://raw.githubusercontent.com/mudler/LocalAI/master/embedded/models/hermes-2-pro-mistral.yaml")
+			Expect(err).To(BeNil())
+			defer resp.Body.Close()
+			tmp, err = os.CreateTemp("", "config.yaml")
+			Expect(err).To(BeNil())
+			defer os.Remove(tmp.Name())
+			_, err = io.Copy(tmp, resp.Body)
+			Expect(err).To(BeNil())
+			config, err = ReadBackendConfig(tmp.Name())
+			Expect(err).To(BeNil())
+			Expect(config).ToNot(BeNil())
+			// two configs in config.yaml
+			Expect(config.Name).To(Equal("hermes-2-pro-mistral"))
+			Expect(config.Validate()).To(BeTrue())
+		})
+	})
+})
diff --git a/core/config/config_suite_test.go b/core/config/config_suite_test.go
new file mode 100644
index 00000000..56052cbb
--- /dev/null
+++ b/core/config/config_suite_test.go
@@ -0,0 +1,13 @@
+package config_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+func TestConfig(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Config test suite")
+}
diff --git a/core/config/config_test.go b/core/config/config_test.go
index b18e083f..eeb5ad89 100644
--- a/core/config/config_test.go
+++ b/core/config/config_test.go
@@ -26,20 +26,15 @@ var _ = Describe("Test cases for config related functions", func() {
 			Expect(config[1].Name).To(Equal("list2"))
 		})
 
 		It("Test LoadConfigs", func() {
 			cm := NewBackendConfigLoader()
-			opts := NewApplicationConfig()
-			err := cm.LoadBackendConfigsFromPath(opts.ModelPath)
+			err := cm.LoadBackendConfigsFromPath(os.Getenv("MODELS_PATH"))
 			Expect(err).To(BeNil())
 			Expect(cm.ListBackendConfigs()).ToNot(BeNil())
 
-			// config should includes gpt4all models's api.config
-			Expect(cm.ListBackendConfigs()).To(ContainElements("gpt4all"))
-
-			// config should includes gpt2 models's api.config
-			Expect(cm.ListBackendConfigs()).To(ContainElements("gpt4all-2"))
+			Expect(cm.ListBackendConfigs()).To(ContainElements("code-search-ada-code-001"))
 
 			// config should includes text-embedding-ada-002 models's api.config
 			Expect(cm.ListBackendConfigs()).To(ContainElements("text-embedding-ada-002"))
 
 			// config should includes rwkv_test models's api.config
diff --git a/pkg/model/process.go b/pkg/model/process.go
index ff3b12cc..b7180f5d 100644
--- a/pkg/model/process.go
+++ b/pkg/model/process.go
@@ -28,12 +28,14 @@ func (ml *ModelLoader) StopAllExcept(s string) error {
 		return false
 	})
 }
 
 func (ml *ModelLoader) deleteProcess(s string) error {
-	if err := ml.grpcProcesses[s].Stop(); err != nil {
-		return err
+	if _, exists := ml.grpcProcesses[s]; exists {
+		if err := ml.grpcProcesses[s].Stop(); err != nil {
+			return err
+		}
 	}
 	delete(ml.grpcProcesses, s)
 	delete(ml.models, s)
 	return nil
 }

Vulnerable code:             GRPC_VERSION=v1.63.0
            GRPC_VERSION=v1.63.0
  GRPC_VERSION: v1.63.0
          pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
  #         pip install --user grpcio-tools==1.63.0
  #         pip install --user grpcio-tools==1.63.0
  #         pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
          pip install --user grpcio-tools==1.63.0
  GRPC_VERSION: v1.63.0
          pip install --user grpcio-tools==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
grpcio==1.63.0
		cm.configs[cc.Name] = *cc
	cl.configs[c.Name] = *c
		return err
		if err == nil {
			opts := NewApplicationConfig()
			err := cm.LoadBackendConfigsFromPath(opts.ModelPath)
			// config should includes gpt4all models's api.config
			Expect(cm.ListBackendConfigs()).To(ContainElements("gpt4all"))

			// config should includes gpt2 models's api.config
			Expect(cm.ListBackendConfigs()).To(ContainElements("gpt4all-2"))
	if err := ml.grpcProcesses[s].Stop(); err != nil {
		return err
Fixed code:             GRPC_VERSION=v1.64.0
            GRPC_VERSION=v1.64.0
  GRPC_VERSION: v1.64.0
          pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
  #         pip install --user grpcio-tools==1.64.0
  #         pip install --user grpcio-tools==1.64.0
  #         pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
          pip install --user grpcio-tools==1.64.0
  GRPC_VERSION: v1.64.0
          pip install --user grpcio-tools==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
grpcio==1.64.0
	"regexp"
	"strings"

func (c *BackendConfig) Validate() bool {
	// Simple validation to make sure the model can be correctly loaded
	for _, n := range []string{c.Backend, c.Model} {
		if strings.HasPrefix(n, string(os.PathSeparator)) ||
			strings.Contains(n, "..") {
			return false
		}
	}

	if c.Name == "" {
		return false
	}

	if c.Backend != "" {
		// a regex that checks that is a string name with no special characters, except '-' and '_'
		re := regexp.MustCompile(`^[a-zA-Z0-9-_]+$`)
		return re.MatchString(c.Backend)
	}

	return true
}
		if cc.Validate() {
			cm.configs[cc.Name] = *cc
		}
	if c.Validate() {
		cl.configs[c.Name] = *c
	} else {
		return fmt.Errorf("config is not valid")
	}

		return fmt.Errorf("cannot read directory '%s': %w", path, err)
		if err != nil {
			log.Error().Err(err).Msgf("cannot read config file: %s", file.Name())
			continue
		}
		if c.Validate() {
		} else {
			log.Error().Err(err).Msgf("config is not valid")
package config_test

import (
	"io"
	"net/http"
	"os"

	. "github.com/go-skynet/LocalAI/core/config"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

var _ = Describe("Test cases for config related functions", func() {
	Context("Test Read configuration functions", func() {
		It("Test Validate", func() {
			tmp, err := os.CreateTemp("", "config.yaml")
			Expect(err).To(BeNil())
			defer os.Remove(tmp.Name())
			_, err = tmp.WriteString(
				`backend: "foo-bar"
parameters:
  model: "foo-bar"`)
			Expect(err).ToNot(HaveOccurred())
			config, err := ReadBackendConfig(tmp.Name())
			Expect(err).To(BeNil())
			Expect(config).ToNot(BeNil())
			Expect(config.Validate()).To(BeFalse())
		})
		It("Test Validate", func() {
			tmp, err := os.CreateTemp("", "config.yaml")
			Expect(err).To(BeNil())
			defer os.Remove(tmp.Name())
			_, err = tmp.WriteString(
				`name: bar-baz
backend: "foo-bar"
parameters:
  model: "foo-bar"`)
			Expect(err).ToNot(HaveOccurred())
			config, err := ReadBackendConfig(tmp.Name())
			Expect(err).To(BeNil())
			Expect(config).ToNot(BeNil())
			// two configs in config.yaml
			Expect(config.Name).To(Equal("bar-baz"))
			Expect(config.Validate()).To(BeTrue())

			// download https://raw.githubusercontent.com/mudler/LocalAI/master/embedded/models/hermes-2-pro-mistral.yaml
			httpClient := http.Client{}
			resp, err := httpClient.Get("https://raw.githubusercontent.com/mudler/LocalAI/master/embedded/models/hermes-2-pro-mistral.yaml")
			Expect(err).To(BeNil())
			defer resp.Body.Close()
			tmp, err = os.CreateTemp("", "config.yaml")
			Expect(err).To(BeNil())
			defer os.Remove(tmp.Name())
			_, err = io.Copy(tmp, resp.Body)
			Expect(err).To(BeNil())
			config, err = ReadBackendConfig(tmp.Name())
			Expect(err).To(BeNil())
			Expect(config).ToNot(BeNil())
			// two configs in config.yaml
			Expect(config.Name).To(Equal("hermes-2-pro-mistral"))
			Expect(config.Validate()).To(BeTrue())
		})
	})
})
package config_test

import (
	"testing"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

func TestConfig(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Config test suite")
}
			err := cm.LoadBackendConfigsFromPath(os.Getenv("MODELS_PATH"))
			Expect(cm.ListBackendConfigs()).To(ContainElements("code-search-ada-code-001"))
	if _, exists := ml.grpcProcesses[s]; exists {
		if err := ml.grpcProcesses[s].Stop(); err != nil {
			return err
		}