oci_test.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. Copyright 2020 Docker Compose CLI authors
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package remote
  14. import (
  15. "path/filepath"
  16. "testing"
  17. spec "github.com/opencontainers/image-spec/specs-go/v1"
  18. "gotest.tools/v3/assert"
  19. )
  20. func TestValidatePathInBase(t *testing.T) {
  21. base := "/tmp/cache/compose"
  22. tests := []struct {
  23. name string
  24. unsafePath string
  25. wantErr bool
  26. }{
  27. {
  28. name: "valid simple filename",
  29. unsafePath: "compose.yaml",
  30. wantErr: false,
  31. },
  32. {
  33. name: "valid hashed filename",
  34. unsafePath: "f8f9ede3d201ec37d5a5e3a77bbadab79af26035e53135e19571f50d541d390c.yaml",
  35. wantErr: false,
  36. },
  37. {
  38. name: "valid env file",
  39. unsafePath: ".env",
  40. wantErr: false,
  41. },
  42. {
  43. name: "valid env file with suffix",
  44. unsafePath: ".env.prod",
  45. wantErr: false,
  46. },
  47. {
  48. name: "unix path traversal",
  49. unsafePath: "../../../etc/passwd",
  50. wantErr: true,
  51. },
  52. {
  53. name: "windows path traversal",
  54. unsafePath: "..\\..\\..\\windows\\system32\\config\\sam",
  55. wantErr: true,
  56. },
  57. {
  58. name: "subdirectory unix",
  59. unsafePath: "config/base.yaml",
  60. wantErr: true,
  61. },
  62. {
  63. name: "subdirectory windows",
  64. unsafePath: "config\\base.yaml",
  65. wantErr: true,
  66. },
  67. {
  68. name: "absolute unix path",
  69. unsafePath: "/etc/passwd",
  70. wantErr: true,
  71. },
  72. {
  73. name: "absolute windows path",
  74. unsafePath: "C:\\windows\\system32\\config\\sam",
  75. wantErr: true,
  76. },
  77. {
  78. name: "parent reference only",
  79. unsafePath: "..",
  80. wantErr: true,
  81. },
  82. {
  83. name: "mixed separators",
  84. unsafePath: "config/sub\\file.yaml",
  85. wantErr: true,
  86. },
  87. {
  88. name: "filename with spaces",
  89. unsafePath: "my file.yaml",
  90. wantErr: false,
  91. },
  92. {
  93. name: "filename with special chars",
  94. unsafePath: "file-name_v1.2.3.yaml",
  95. wantErr: false,
  96. },
  97. }
  98. for _, tt := range tests {
  99. t.Run(tt.name, func(t *testing.T) {
  100. err := validatePathInBase(base, tt.unsafePath)
  101. if (err != nil) != tt.wantErr {
  102. targetPath := filepath.Join(base, tt.unsafePath)
  103. targetDir := filepath.Dir(targetPath)
  104. t.Errorf("validatePathInBase(%q, %q) error = %v, wantErr %v\ntargetDir=%q base=%q",
  105. base, tt.unsafePath, err, tt.wantErr, targetDir, base)
  106. }
  107. })
  108. }
  109. }
  110. func TestWriteComposeFileWithExtendsPathTraversal(t *testing.T) {
  111. tmpDir := t.TempDir()
  112. // Create a layer with com.docker.compose.extends=true and a path traversal attempt
  113. layer := spec.Descriptor{
  114. MediaType: "application/vnd.docker.compose.file.v1+yaml",
  115. Digest: "sha256:test123",
  116. Size: 100,
  117. Annotations: map[string]string{
  118. "com.docker.compose.extends": "true",
  119. "com.docker.compose.file": "../other",
  120. },
  121. }
  122. content := []byte("services:\n test:\n image: nginx\n")
  123. // writeComposeFile should return an error due to path traversal
  124. err := writeComposeFile(layer, 0, tmpDir, content)
  125. assert.Error(t, err, "invalid OCI artifact")
  126. }