Skip to content

Commit aaeaf0b

Browse files
use fileutil.SafePathJoin instead
Signed-off-by: Tim Vaillancourt <tim@timvaillancourt.com>
1 parent 34b70e0 commit aaeaf0b

2 files changed

Lines changed: 18 additions & 22 deletions

File tree

go/vt/mysqlctl/builtinbackupengine.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ import (
3030
"path"
3131
"path/filepath"
3232
"strconv"
33-
"strings"
3433
"sync/atomic"
3534
"time"
3635

3736
"github.com/spf13/pflag"
3837
"golang.org/x/sync/errgroup"
3938

39+
"vitess.io/vitess/go/fileutil"
4040
"vitess.io/vitess/go/ioutil"
4141
"vitess.io/vitess/go/mysql"
4242
"vitess.io/vitess/go/mysql/replication"
@@ -200,14 +200,7 @@ func (fe *FileEntry) fullPath(cnf *Mycnf) (string, error) {
200200
return "", vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "unknown base: %v", fe.Base)
201201
}
202202

203-
baseDir := filepath.Clean(path.Join(fe.ParentPath, root))
204-
resolved := filepath.Clean(path.Join(baseDir, fe.Name))
205-
206-
if !strings.HasPrefix(resolved, baseDir+string(filepath.Separator)) && resolved != baseDir {
207-
return "", vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "path traversal not allowed: name %q escapes base directory %q", fe.Name, baseDir)
208-
}
209-
210-
return resolved, nil
203+
return fileutil.SafePathJoin(path.Join(fe.ParentPath, root), fe.Name)
211204
}
212205

213206
// open attempts to open the file

go/vt/mysqlctl/builtinbackupengine_test.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/stretchr/testify/assert"
2424
"github.com/stretchr/testify/require"
2525

26+
"vitess.io/vitess/go/fileutil"
2627
tabletmanagerdatapb "vitess.io/vitess/go/vt/proto/tabletmanagerdata"
2728
)
2829

@@ -83,7 +84,7 @@ func TestFileEntryFullPath(t *testing.T) {
8384
name string
8485
entry FileEntry
8586
wantPath string
86-
wantError string
87+
wantError error
8788
}{
8889
{
8990
name: "valid relative path in DataDir",
@@ -113,41 +114,43 @@ func TestFileEntryFullPath(t *testing.T) {
113114
{
114115
name: "path traversal escapes base directory",
115116
entry: FileEntry{Base: backupData, Name: "../../etc/passwd"},
116-
wantError: "path traversal not allowed",
117+
wantError: fileutil.ErrInvalidJoinedPath,
117118
},
118119
{
119120
name: "path traversal with deeper nesting",
120121
entry: FileEntry{Base: backupData, Name: "mydb/../../../etc/shadow"},
121-
wantError: "path traversal not allowed",
122+
wantError: fileutil.ErrInvalidJoinedPath,
122123
},
123124
{
124125
name: "path traversal to root",
125126
entry: FileEntry{Base: backupData, Name: "../../../../../etc/crontab"},
126-
wantError: "path traversal not allowed",
127+
wantError: fileutil.ErrInvalidJoinedPath,
127128
},
128129
{
129130
name: "path traversal escapes ParentPath",
130131
entry: FileEntry{Base: backupData, Name: "../../../../etc/passwd", ParentPath: "/tmp/restore"},
131-
wantError: "path traversal not allowed",
132+
wantError: fileutil.ErrInvalidJoinedPath,
132133
},
133134
{
134135
name: "relative path with dot-dot that stays within base",
135136
entry: FileEntry{Base: backupData, Name: "mydb/../mydb/table1.ibd"},
136137
wantPath: "/vt/data/mydb/table1.ibd",
137138
},
138-
{
139-
name: "unknown base",
140-
entry: FileEntry{Base: "unknown", Name: "file"},
141-
wantError: "unknown base",
142-
},
143139
}
144140

141+
// Test unknown base separately since it returns a different error type.
142+
t.Run("unknown base", func(t *testing.T) {
143+
entry := FileEntry{Base: "unknown", Name: "file"}
144+
_, err := entry.fullPath(cnf)
145+
require.Error(t, err)
146+
assert.Contains(t, err.Error(), "unknown base")
147+
})
148+
145149
for _, tt := range tests {
146150
t.Run(tt.name, func(t *testing.T) {
147151
got, err := tt.entry.fullPath(cnf)
148-
if tt.wantError != "" {
149-
require.Error(t, err)
150-
assert.Contains(t, err.Error(), tt.wantError)
152+
if tt.wantError != nil {
153+
require.ErrorIs(t, err, tt.wantError)
151154
} else {
152155
require.NoError(t, err)
153156
assert.Equal(t, tt.wantPath, got)

0 commit comments

Comments
 (0)