Skip to content

Commit 3929fea

Browse files
use SafeJoin on tools Remove handler
1 parent 5d674c8 commit 3929fea

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

v2/pkgs/tools.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"strings"
3232

3333
"github.com/arduino/arduino-create-agent/gen/tools"
34+
"github.com/arduino/arduino-create-agent/utilities"
3435
"github.com/codeclysm/extract/v3"
3536
)
3637

@@ -216,8 +217,12 @@ func (c *Tools) install(ctx context.Context, path, url, checksum string) (*tools
216217
// Remove deletes the tool folder from Tools Folder
217218
func (c *Tools) Remove(ctx context.Context, payload *tools.ToolPayload) (*tools.Operation, error) {
218219
path := filepath.Join(payload.Packager, payload.Name, payload.Version)
220+
pathToRemove, err := utilities.SafeJoin(c.Folder, path)
221+
if err != nil {
222+
return nil, err
223+
}
219224

220-
err := os.RemoveAll(filepath.Join(c.Folder, path))
225+
err = os.RemoveAll(pathToRemove)
221226
if err != nil {
222227
return nil, err
223228
}

v2/pkgs/tools_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/arduino/arduino-create-agent/gen/indexes"
2828
"github.com/arduino/arduino-create-agent/gen/tools"
2929
"github.com/arduino/arduino-create-agent/v2/pkgs"
30+
"github.com/stretchr/testify/require"
3031
)
3132

3233
// TestTools performs a series of operations about tools, ensuring it behaves as expected.
@@ -150,6 +151,33 @@ func TestTools(t *testing.T) {
150151
if len(installed) != 1 {
151152
t.Fatalf("expected %d == %d (%s)", len(installed), 1, "len(installed)")
152153
}
154+
155+
t.Run("payload containing evil names", func(t *testing.T) {
156+
evilFileNames := []string{
157+
"/",
158+
"..",
159+
"../",
160+
"../evil.txt",
161+
"../../../../../../../../../../../../../../../../../../../../tmp/evil.txt",
162+
"some/path/../../../../../../../../../../../../../../../../../../../../tmp/evil.txt",
163+
}
164+
if runtime.GOOS == "windows" {
165+
evilFileNames = []string{
166+
"..\\",
167+
"..\\evil.txt",
168+
"..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\tmp\\evil.txt",
169+
"some\\path\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\tmp\\evil.txt",
170+
}
171+
}
172+
for _, evilFileName := range evilFileNames {
173+
// Here we could inject malicious name also in the Packager and Version field.
174+
// Since the path is made by joining all of these 3 fields, we're using only the Name,
175+
// as it won't change the result and let us keep the test small and readable.
176+
_, err := service.Remove(ctx, &tools.ToolPayload{Name: evilFileName})
177+
require.Error(t, err, evilFileName)
178+
require.ErrorContains(t, err, "unsafe path join")
179+
}
180+
})
153181
}
154182

155183
func strpoint(s string) *string {

0 commit comments

Comments
 (0)