Skip to content

Commit 5928a5d

Browse files
anmaxvlkiashok
authored andcommitted
update newBinaryCmd URL path handling (#2041)
Signed-off-by: Maksim An <maksiman@microsoft.com> (cherry picked from commit fe8c673) Signed-off-by: Kirtana Ashok <kiashok@microsoft.com>
1 parent f79d88e commit 5928a5d

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

internal/cmd/io_binary.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ const (
2828
binaryCmdStartTimeout = 10 * time.Second
2929
)
3030

31+
var ErrUnsafePath = errors.New("path is unsafe")
32+
3133
// NewBinaryIO runs a custom binary process for pluggable shim logging driver.
3234
//
3335
// Container's IO will be redirected to the logging driver via named pipes, which are
@@ -122,14 +124,19 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (_ UpstreamIO, er
122124
}
123125

124126
// sanitizePath parses the URL object and returns a clean path to the logging driver
125-
func sanitizePath(uri *url.URL) string {
127+
func sanitizePath(uri *url.URL) (string, error) {
126128
path := filepath.Clean(uri.Path)
127129

130+
// avoid UNC paths (e.g. `\\server\share\`)
131+
if strings.HasPrefix(path, `\\`) {
132+
return "", ErrUnsafePath
133+
}
134+
128135
if strings.Contains(path, `:\`) {
129-
return strings.TrimPrefix(path, "\\")
136+
return strings.TrimPrefix(path, "\\"), nil
130137
}
131138

132-
return path
139+
return path, nil
133140
}
134141

135142
func newBinaryCmd(ctx context.Context, uri *url.URL, envs []string) (*exec.Cmd, error) {
@@ -145,7 +152,10 @@ func newBinaryCmd(ctx context.Context, uri *url.URL, envs []string) (*exec.Cmd,
145152
}
146153
}
147154

148-
execPath := sanitizePath(uri)
155+
execPath, err := sanitizePath(uri)
156+
if err != nil {
157+
return nil, err
158+
}
149159

150160
cmd := exec.CommandContext(ctx, execPath, args...)
151161
cmd.Env = append(cmd.Env, envs...)

internal/cmd/io_binary_test.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package cmd
44

55
import (
66
"context"
7+
"errors"
78
"net/url"
89
"testing"
910
)
@@ -24,11 +25,6 @@ func Test_newBinaryCmd_Key_Value_Pair(t *testing.T) {
2425
urlString: "binary:///executable?-key=value",
2526
expected: `\executable -key value`,
2627
},
27-
{
28-
name: "Path_With_Back_Slashes",
29-
urlString: `binary:///\executable?-key=value`,
30-
expected: `\executable -key value`,
31-
},
3228
{
3329
name: "Clean_Path_With_Dots_And_Multiple_Fwd_Slashes",
3430
urlString: "binary:///../path/to///to/../executable",
@@ -70,6 +66,45 @@ func Test_newBinaryCmd_Key_Value_Pair(t *testing.T) {
7066
}
7167
}
7268

69+
func Test_newBinaryCmd_Unsafe_Path(t *testing.T) {
70+
ctx, cancel := context.WithCancel(context.Background())
71+
defer cancel()
72+
73+
type config struct {
74+
name string
75+
urlString string
76+
expectedError error
77+
}
78+
79+
for _, cfg := range []*config{
80+
{
81+
name: "UNC_Path_With_Back_Slashes",
82+
urlString: `binary:///\server\share\executable`,
83+
expectedError: ErrUnsafePath,
84+
},
85+
{
86+
name: "UNC_Path_With_Forward_Slashes",
87+
urlString: `binary:////server/share/executable`,
88+
expectedError: ErrUnsafePath,
89+
},
90+
} {
91+
t.Run(cfg.name, func(t *testing.T) {
92+
u, err := url.Parse(cfg.urlString)
93+
if err != nil {
94+
t.Fatalf("failed to parse url: %s", cfg.urlString)
95+
}
96+
97+
_, err = newBinaryCmd(ctx, u, nil)
98+
if err == nil {
99+
t.Fatalf("no error was returned")
100+
}
101+
if !errors.Is(err, cfg.expectedError) {
102+
t.Fatalf("expected error: %s, actual: %s", cfg.expectedError, err)
103+
}
104+
})
105+
}
106+
}
107+
73108
func Test_newBinaryCmd_Empty_Path(t *testing.T) {
74109
ctx, cancel := context.WithCancel(context.Background())
75110
defer cancel()

0 commit comments

Comments
 (0)