Skip to content

Commit d0c6cb2

Browse files
committed
Fix traversal checks and USB config unquoting
1 parent 628a737 commit d0c6cb2

3 files changed

Lines changed: 32 additions & 5 deletions

File tree

snapshots.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"io"
99
"os"
1010
"path/filepath"
11+
"strings"
1112
"testing"
1213
)
1314

@@ -179,7 +180,7 @@ func safeJoin(base, name string) (string, error) {
179180
if filepath.IsAbs(cleanName) {
180181
return "", fmt.Errorf("absolute paths are not allowed")
181182
}
182-
if cleanName == ".." || len(cleanName) >= 3 && cleanName[:3] == ".."+string(filepath.Separator) {
183+
if cleanName == ".." || strings.HasPrefix(cleanName, ".."+string(filepath.Separator)) {
183184
return "", fmt.Errorf("path traversal is not allowed")
184185
}
185186

@@ -188,7 +189,7 @@ func safeJoin(base, name string) (string, error) {
188189
if err != nil {
189190
return "", err
190191
}
191-
if rel == ".." || len(rel) >= 3 && rel[:3] == ".."+string(filepath.Separator) {
192+
if rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
192193
return "", fmt.Errorf("resolved path escapes restore directory")
193194
}
194195

usb_fixtures.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ func validateFixtureLayoutDir(layoutDir string) error {
2828
}
2929

3030
type USBVolumeOptions struct {
31-
LayoutDir string
32-
Strategy string
31+
LayoutDir string
32+
Strategy string
3333
CreateReposDir bool
3434
}
3535

@@ -109,7 +109,7 @@ func readUSBVolumeConfigBytes(data []byte) (USBVolumeConfig, error) {
109109
continue
110110
}
111111
key = strings.TrimSpace(key)
112-
val = strings.Trim(strings.TrimSpace(val), "\"")
112+
val = strings.TrimSpace(val)
113113
switch key {
114114
case "schema_version":
115115
n, err := strconv.Atoi(val)
@@ -118,6 +118,9 @@ func readUSBVolumeConfigBytes(data []byte) (USBVolumeConfig, error) {
118118
}
119119
cfg.SchemaVersion = n
120120
case "layout_dir":
121+
if unquoted, err := strconv.Unquote(val); err == nil {
122+
val = unquoted
123+
}
121124
if err := validateFixtureLayoutDir(val); err != nil {
122125
return cfg, fmt.Errorf("layout_dir: %w", err)
123126
}
@@ -127,8 +130,14 @@ func readUSBVolumeConfigBytes(data []byte) (USBVolumeConfig, error) {
127130
cfg.LayoutDir = filepath.Clean(val)
128131
}
129132
case "strategy":
133+
if unquoted, err := strconv.Unquote(val); err == nil {
134+
val = unquoted
135+
}
130136
cfg.Strategy = val
131137
case "created_at":
138+
if unquoted, err := strconv.Unquote(val); err == nil {
139+
val = unquoted
140+
}
132141
if val == "" {
133142
return cfg, fmt.Errorf("created_at: empty value")
134143
}

usb_fixtures_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ func TestReadWriteUSBVolumeConfig(t *testing.T) {
4141
}
4242
}
4343

44+
func TestReadWriteUSBVolumeConfig_preservesEscapedChars(t *testing.T) {
45+
root := t.TempDir()
46+
WriteUSBVolumeConfig(t, root, USBVolumeConfig{
47+
SchemaVersion: 1,
48+
LayoutDir: `repo\"dir\path`,
49+
Strategy: `mirror\"strategy\mode`,
50+
})
51+
52+
cfg := ReadUSBVolumeConfig(t, root)
53+
if cfg.LayoutDir != `repo\"dir\path` {
54+
t.Fatalf("layout mismatch: got %q", cfg.LayoutDir)
55+
}
56+
if cfg.Strategy != `mirror\"strategy\mode` {
57+
t.Fatalf("strategy mismatch: got %q", cfg.Strategy)
58+
}
59+
}
60+
4461
func TestValidateFixtureLayoutDir(t *testing.T) {
4562
t.Parallel()
4663
root := t.TempDir()

0 commit comments

Comments
 (0)