Clean paths when looking in Storage (#19124)
* Clean paths when looking in Storage Ensure paths are clean for minio aswell as local storage. Use url.Path not RequestURI/EscapedPath in storageHandler. Signed-off-by: Andrew Thornton <art27@cantab.net> * Apply suggestions from code review Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
parent
d2c165811a
commit
3f71ab9a12
4 changed files with 40 additions and 51 deletions
|
@ -6,7 +6,6 @@ package storage
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -18,8 +17,6 @@ import (
|
|||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// ErrLocalPathNotSupported represents an error that path is not supported
|
||||
var ErrLocalPathNotSupported = errors.New("local path is not supported")
|
||||
var _ ObjectStorage = &LocalStorage{}
|
||||
|
||||
// LocalStorageType is the type descriptor for local storage
|
||||
|
@ -62,21 +59,18 @@ func NewLocalStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (l *LocalStorage) buildLocalPath(p string) string {
|
||||
return filepath.Join(l.dir, path.Clean("/" + strings.ReplaceAll(p, "\\", "/"))[1:])
|
||||
}
|
||||
|
||||
// Open a file
|
||||
func (l *LocalStorage) Open(path string) (Object, error) {
|
||||
if !isLocalPathValid(path) {
|
||||
return nil, ErrLocalPathNotSupported
|
||||
}
|
||||
return os.Open(filepath.Join(l.dir, path))
|
||||
return os.Open(l.buildLocalPath(path))
|
||||
}
|
||||
|
||||
// Save a file
|
||||
func (l *LocalStorage) Save(path string, r io.Reader, size int64) (int64, error) {
|
||||
if !isLocalPathValid(path) {
|
||||
return 0, ErrLocalPathNotSupported
|
||||
}
|
||||
|
||||
p := filepath.Join(l.dir, path)
|
||||
p := l.buildLocalPath(path)
|
||||
if err := os.MkdirAll(filepath.Dir(p), os.ModePerm); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -116,24 +110,12 @@ func (l *LocalStorage) Save(path string, r io.Reader, size int64) (int64, error)
|
|||
|
||||
// Stat returns the info of the file
|
||||
func (l *LocalStorage) Stat(path string) (os.FileInfo, error) {
|
||||
return os.Stat(filepath.Join(l.dir, path))
|
||||
}
|
||||
|
||||
func isLocalPathValid(p string) bool {
|
||||
a := path.Clean(p)
|
||||
if strings.HasPrefix(a, "../") || strings.HasPrefix(a, "..\\") {
|
||||
return false
|
||||
}
|
||||
return a == p
|
||||
return os.Stat(l.buildLocalPath(path))
|
||||
}
|
||||
|
||||
// Delete delete a file
|
||||
func (l *LocalStorage) Delete(path string) error {
|
||||
if !isLocalPathValid(path) {
|
||||
return ErrLocalPathNotSupported
|
||||
}
|
||||
p := filepath.Join(l.dir, path)
|
||||
return util.Remove(p)
|
||||
return util.Remove(l.buildLocalPath(path))
|
||||
}
|
||||
|
||||
// URL gets the redirect URL to a file
|
||||
|
|
|
@ -10,36 +10,44 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLocalPathIsValid(t *testing.T) {
|
||||
func TestBuildLocalPath(t *testing.T) {
|
||||
kases := []struct {
|
||||
path string
|
||||
valid bool
|
||||
localDir string
|
||||
path string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
"a",
|
||||
"0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
"a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"../a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
false,
|
||||
"a",
|
||||
"../0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
"a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
},
|
||||
{
|
||||
"a\\0\\a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
true,
|
||||
"a",
|
||||
"0\\a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
"a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
},
|
||||
{
|
||||
"b/../a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
false,
|
||||
"b",
|
||||
"a/../0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
"b/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
},
|
||||
{
|
||||
"..\\a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
false,
|
||||
"b",
|
||||
"a\\..\\0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
"b/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
|
||||
},
|
||||
}
|
||||
|
||||
for _, k := range kases {
|
||||
t.Run(k.path, func(t *testing.T) {
|
||||
assert.EqualValues(t, k.valid, isLocalPathValid(k.path))
|
||||
l := LocalStorage{dir: k.localDir}
|
||||
|
||||
assert.EqualValues(t, k.expected, l.buildLocalPath(k.path))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ func NewMinioStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
|
|||
}
|
||||
|
||||
func (m *MinioStorage) buildMinioPath(p string) string {
|
||||
return strings.TrimPrefix(path.Join(m.basePath, p), "/")
|
||||
return strings.TrimPrefix(path.Join(m.basePath, path.Clean("/" + strings.ReplaceAll(p, "\\", "/"))[1:]), "/")
|
||||
}
|
||||
|
||||
// Open open a file
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue