Skip to content

Commit 7d736f4

Browse files
Pradip RoutaGitHub Enterprise
authored andcommitted
PathTraversal vulnerabilities in container test code fix (#581)
* PathTraversal vulnerabilities in container test code fixed * PathTraversal vulnerabilities in container test code fixed * Added comments for RemoveContainerDirectory * used replace method instead of regual expression * test case failure fixed * Fixed path travesal issue * removed method * updated copy right version * Changed copyright version
1 parent c7525cb commit 7d736f4

File tree

5 files changed

+59
-15
lines changed

5 files changed

+59
-15
lines changed

test/container/containerengine/containerengine.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
© Copyright IBM Corporation 2017, 2023
2+
© Copyright IBM Corporation 2017, 2024
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -25,6 +25,8 @@ import (
2525
"strconv"
2626
"strings"
2727
"time"
28+
29+
"github.com/ibm-messaging/mq-container/test/container/pathutils"
2830
)
2931

3032
type ContainerInterface interface {
@@ -305,13 +307,13 @@ func (cli ContainerClient) CopyFromContainer(container, srcPath string) ([]byte,
305307
}
306308
//Get file name
307309
fname := filepath.Base(srcPath)
308-
data, err := os.ReadFile(filepath.Join(tmpDir, fname))
310+
data, err := os.ReadFile(pathutils.CleanPath(tmpDir, fname))
309311
if err != nil {
310312
return nil, err
311313
}
312314

313315
//Remove the file
314-
err = os.Remove(filepath.Join(tmpDir, fname))
316+
err = os.Remove(pathutils.CleanPath(tmpDir, fname))
315317
if err != nil {
316318
return nil, err
317319
}

test/container/devconfig_test_util.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// +build mqdev
33

44
/*
5-
© Copyright IBM Corporation 2018, 2023
5+
© Copyright IBM Corporation 2018, 2024
66
77
Licensed under the Apache License, Version 2.0 (the "License");
88
you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import (
3636
"time"
3737

3838
ce "github.com/ibm-messaging/mq-container/test/container/containerengine"
39+
"github.com/ibm-messaging/mq-container/test/container/pathutils"
3940
)
4041

4142
const defaultAdminPassword string = "passw0rd"
@@ -82,15 +83,15 @@ func waitForWebReady(t *testing.T, cli ce.ContainerInterface, ID string, tlsConf
8283

8384
// tlsDir returns the host directory where the test certificate(s) are located
8485
func tlsDir(t *testing.T, unixPath bool) string {
85-
return filepath.Join(getCwd(t, unixPath), "../tls")
86+
return pathutils.CleanPath(filepath.Dir(getCwd(t, unixPath)), "../tls")
8687
}
8788

8889
func tlsDirWithCA(t *testing.T, unixPath bool) string {
89-
return filepath.Join(getCwd(t, unixPath), "../tlscacert")
90+
return pathutils.CleanPath(filepath.Dir(getCwd(t, unixPath)), "../tlscacert")
9091
}
9192

9293
func tlsDirInvalid(t *testing.T, unixPath bool) string {
93-
return filepath.Join(getCwd(t, unixPath), "../tlsinvalidcert")
94+
return pathutils.CleanPath(filepath.Dir(getCwd(t, unixPath)), "../tlsinvalidcert")
9495
}
9596

9697
// runJMSTests runs a container with a JMS client, which connects to the queue manager container with the specified ID

test/container/docker_api_test_util.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
© Copyright IBM Corporation 2017, 2023
2+
© Copyright IBM Corporation 2017, 2024
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import (
3434
"time"
3535

3636
ce "github.com/ibm-messaging/mq-container/test/container/containerengine"
37+
"github.com/ibm-messaging/mq-container/test/container/pathutils"
3738
)
3839

3940
func imageName() string {
@@ -129,7 +130,7 @@ func coverage() bool {
129130

130131
// coverageDir returns the host directory to use for code coverage data
131132
func coverageDir(t *testing.T, unixStylePath bool) string {
132-
return filepath.Join(getCwd(t, unixStylePath), "coverage")
133+
return pathutils.CleanPath(getCwd(t, unixStylePath), "coverage")
133134
}
134135

135136
// coverageBind returns a string to use to add a bind-mounted directory for code coverage data
@@ -213,7 +214,7 @@ func cleanContainer(t *testing.T, cli ce.ContainerInterface, ID string) {
213214
t.Log("Container stopped")
214215

215216
// If a code coverage file has been generated, then rename it to match the test name
216-
os.Rename(filepath.Join(coverageDir(t, true), "container.cov"), filepath.Join(coverageDir(t, true), t.Name()+".cov"))
217+
os.Rename(pathutils.CleanPath(coverageDir(t, true), "container.cov"), pathutils.CleanPath(coverageDir(t, true), t.Name()+".cov"))
217218
// Log the container output for any container we're about to delete
218219
t.Logf("Console log from container %v:\n%v", ID, inspectTextLogs(t, cli, ID))
219220

@@ -507,7 +508,7 @@ func getExitCodeFilename(t *testing.T) string {
507508
}
508509

509510
func getCoverageExitCode(t *testing.T, orig int64) int64 {
510-
f := filepath.Join(coverageDir(t, true), getExitCodeFilename(t))
511+
f := pathutils.CleanPath(coverageDir(t, true), getExitCodeFilename(t))
511512
_, err := os.Stat(f)
512513
if err != nil {
513514
t.Log(err)
@@ -699,7 +700,7 @@ func createImage(t *testing.T, cli ce.ContainerInterface, files []struct{ Name,
699700
//Write files to temp directory
700701
for _, file := range files {
701702
//Add tag to file name to allow parallel testing
702-
f, err := os.Create(filepath.Join(tmpDir, file.Name))
703+
f, err := os.Create(pathutils.CleanPath(tmpDir, file.Name))
703704
if err != nil {
704705
t.Fatal(err)
705706
}
@@ -711,7 +712,7 @@ func createImage(t *testing.T, cli ce.ContainerInterface, files []struct{ Name,
711712
t.Fatal(err)
712713
}
713714
}
714-
_, err = cli.ImageBuild(r, tag, filepath.Join(tmpDir, files[0].Name))
715+
_, err = cli.ImageBuild(r, tag, pathutils.CleanPath(tmpDir, files[0].Name))
715716
if err != nil {
716717
t.Fatal(err)
717718
}
@@ -876,5 +877,5 @@ func waitForMessageCountInLog(t *testing.T, cli ce.ContainerInterface, id string
876877

877878
// Returns fully qualified path
878879
func tlsDirDN(t *testing.T, unixPath bool, certPath string) string {
879-
return filepath.Join(getCwd(t, unixPath), certPath)
880+
return pathutils.CleanPath(filepath.Dir(getCwd(t, unixPath)), certPath)
880881
}

test/container/mq_native_ha_test_util.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"time"
2525

2626
ce "github.com/ibm-messaging/mq-container/test/container/containerengine"
27+
"github.com/ibm-messaging/mq-container/test/container/pathutils"
2728
)
2829

2930
const defaultHAPort = 9414
@@ -59,7 +60,7 @@ func getNativeHASecureHostConfig(t *testing.T) ce.ContainerHostConfig {
5960
return ce.ContainerHostConfig{
6061
Binds: []string{
6162
coverageBind(t),
62-
filepath.Join(getCwd(t, true), "../tls") + ":/etc/mqm/ha/pki/keys/ha",
63+
pathutils.CleanPath(filepath.Dir(getCwd(t, true)), "../tls") + ":/etc/mqm/ha/pki/keys/ha",
6364
},
6465
}
6566
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
© Copyright IBM Corporation 2024
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package pathutils contains code to provide sanitised file paths
18+
package pathutils
19+
20+
import (
21+
"path"
22+
"path/filepath"
23+
)
24+
25+
// CleanPath returns the result of joining a series of sanitised file paths (preventing directory traversal for each path)
26+
// If the first path is relative, a relative path is returned
27+
func CleanPath(paths ...string) string {
28+
if len(paths) == 0 {
29+
return ""
30+
}
31+
var combined string
32+
if !path.IsAbs(paths[0]) {
33+
combined = "./"
34+
}
35+
for _, part := range paths {
36+
combined = filepath.Join(combined, filepath.FromSlash(path.Clean("/"+part)))
37+
}
38+
return combined
39+
}

0 commit comments

Comments
 (0)