err on insecure path

This commit is contained in:
Michael Yang 2024-06-30 11:10:40 -07:00
parent e70610ef06
commit 88bcd79bb9
2 changed files with 25 additions and 7 deletions

View file

@ -11,7 +11,6 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/ollama/ollama/api" "github.com/ollama/ollama/api"
"github.com/ollama/ollama/convert" "github.com/ollama/ollama/convert"
@ -91,12 +90,11 @@ func extractFromZipFile(p string, file *os.File, fn func(api.ProgressResponse))
fn(api.ProgressResponse{Status: "unpacking model metadata"}) fn(api.ProgressResponse{Status: "unpacking model metadata"})
for _, f := range r.File { for _, f := range r.File {
n := filepath.Join(p, f.Name) if !filepath.IsLocal(f.Name) {
if !strings.HasPrefix(n, p) { return fmt.Errorf("%w: %s", zip.ErrInsecurePath, f.Name)
slog.Warn("skipped extracting file outside of context", "name", f.Name)
continue
} }
n := filepath.Join(p, f.Name)
if err := os.MkdirAll(filepath.Dir(n), 0o750); err != nil { if err := os.MkdirAll(filepath.Dir(n), 0o750); err != nil {
return err return err
} }

View file

@ -3,10 +3,12 @@ package server
import ( import (
"archive/zip" "archive/zip"
"bytes" "bytes"
"errors"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"slices" "slices"
"strings"
"testing" "testing"
"github.com/ollama/ollama/api" "github.com/ollama/ollama/api"
@ -39,13 +41,31 @@ func TestExtractFromZipFile(t *testing.T) {
cases := []struct { cases := []struct {
name string name string
expect []string expect []string
err error
}{ }{
{ {
name: "good", name: "good",
expect: []string{"good"}, expect: []string{"good"},
}, },
{ {
name: filepath.Join("..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "bad"), name: strings.Join([]string{"path", "..", "to", "good"}, string(os.PathSeparator)),
expect: []string{filepath.Join("to", "good")},
},
{
name: strings.Join([]string{"path", "..", "to", "..", "good"}, string(os.PathSeparator)),
expect: []string{"good"},
},
{
name: strings.Join([]string{"path", "to", "..", "..", "good"}, string(os.PathSeparator)),
expect: []string{"good"},
},
{
name: strings.Join([]string{"..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "..", "bad"}, string(os.PathSeparator)),
err: zip.ErrInsecurePath,
},
{
name: strings.Join([]string{"path", "..", "..", "to", "bad"}, string(os.PathSeparator)),
err: zip.ErrInsecurePath,
}, },
} }
@ -55,7 +75,7 @@ func TestExtractFromZipFile(t *testing.T) {
defer f.Close() defer f.Close()
tempDir := t.TempDir() tempDir := t.TempDir()
if err := extractFromZipFile(tempDir, f, func(api.ProgressResponse) {}); err != nil { if err := extractFromZipFile(tempDir, f, func(api.ProgressResponse) {}); !errors.Is(err, tt.err) {
t.Fatal(err) t.Fatal(err)
} }