Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit ddd06c5

Browse files
authored
codeintel: fix panic in extracting JARs with absolute paths (#24652)
1 parent e736604 commit ddd06c5

File tree

2 files changed

+55
-15
lines changed

2 files changed

+55
-15
lines changed

cmd/gitserver/server/vcs_syncer_jvm_packages.go

+9-15
Original file line numberDiff line numberDiff line change
@@ -345,18 +345,7 @@ func unzipJarFile(jarPath, destination string) (err error) {
345345
defer reader.Close()
346346
destinationDirectory := strings.TrimSuffix(destination, string(os.PathSeparator)) + string(os.PathSeparator)
347347

348-
var (
349-
_file *zip.File
350-
outputPath string
351-
)
352-
defer func() {
353-
if r := recover(); r != nil {
354-
err = errors.Newf("panic in extracting JAR: jarPath=%s file=%s jarFilesCount=%d outputPath=%s panic=%v", jarPath, _file.Name, len(reader.File), outputPath, r)
355-
}
356-
}()
357-
358348
for _, file := range reader.File {
359-
_file = file
360349
if strings.HasPrefix(file.Name, ".git/") {
361350
// For security reasons, don't unzip files under the `.git/`
362351
// directory. See https://github.com/sourcegraph/security-issues/issues/163
@@ -368,14 +357,19 @@ func unzipJarFile(jarPath, destination string) (err error) {
368357
// `file.Name` docstring.
369358
continue
370359
}
371-
outputPath = path.Join(destination, file.Name)
360+
if strings.HasPrefix(file.Name, "/") {
361+
// Skip absolute paths. While they are extracted relative to `destination`,
362+
// they should be unimportant. Related issue https://github.com/golang/go/issues/48085#issuecomment-912659635
363+
continue
364+
}
365+
outputPath := path.Join(destination, file.Name)
372366
if !strings.HasPrefix(outputPath, destinationDirectory) {
373367
// For security reasons, skip file if it's not a child
374368
// of the target directory. See "Zip Slip Vulnerability".
375369
continue
376370
}
377371

378-
err := copyZipFileEntry(reader, file, outputPath)
372+
err := copyZipFileEntry(file, outputPath)
379373
if err != nil {
380374
return err
381375
}
@@ -384,8 +378,8 @@ func unzipJarFile(jarPath, destination string) (err error) {
384378
return nil
385379
}
386380

387-
func copyZipFileEntry(reader *zip.ReadCloser, entry *zip.File, outputPath string) (err error) {
388-
inputFile, err := reader.Open(entry.Name)
381+
func copyZipFileEntry(entry *zip.File, outputPath string) (err error) {
382+
inputFile, err := entry.Open()
389383
if err != nil {
390384
return err
391385
}

cmd/gitserver/server/vcs_syncer_jvm_packages_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/stretchr/testify/assert"
1515

1616
"github.com/sourcegraph/sourcegraph/internal/codeintel/stores/dbstore"
17+
"github.com/sourcegraph/sourcegraph/internal/conf/reposource"
1718
"github.com/sourcegraph/sourcegraph/internal/extsvc/jvmpackages/coursier"
1819
"github.com/sourcegraph/sourcegraph/internal/vcs"
1920
"github.com/sourcegraph/sourcegraph/schema"
@@ -117,6 +118,51 @@ func (s JVMPackagesSyncer) runCloneCommand(t *testing.T, bareGitDirectory string
117118
assert.Nil(t, cmd.Run())
118119
}
119120

121+
func TestNoMaliciousFiles(t *testing.T) {
122+
dir, err := os.MkdirTemp("", "")
123+
assert.Nil(t, err)
124+
defer os.RemoveAll(dir)
125+
126+
jarPath := path.Join(dir, "sampletext.zip")
127+
extractPath := path.Join(dir, "extracted")
128+
assert.Nil(t, os.Mkdir(extractPath, os.ModePerm))
129+
130+
createMaliciousJar(t, jarPath)
131+
132+
s := JVMPackagesSyncer{
133+
Config: &schema.JVMPackagesConnection{Maven: &schema.Maven{Dependencies: []string{}}},
134+
DBStore: &simpleJVMPackageDBStoreMock{},
135+
}
136+
137+
ctx, cancel := context.WithCancel(context.Background())
138+
cancel() // cancel now to prevent any network IO
139+
err = s.commitJar(ctx, reposource.MavenDependency{}, extractPath, jarPath, &schema.JVMPackagesConnection{Maven: &schema.Maven{}})
140+
assert.NotNil(t, err)
141+
142+
files, err := os.ReadDir(extractPath)
143+
assert.Nil(t, err)
144+
assert.Equal(t, 2, len(files))
145+
}
146+
147+
func createMaliciousJar(t *testing.T, name string) {
148+
f, err := os.Create(name)
149+
assert.Nil(t, err)
150+
defer f.Close()
151+
writer := zip.NewWriter(f)
152+
defer writer.Close()
153+
154+
_, err = writer.Create("/")
155+
assert.Nil(t, err)
156+
_, err = writer.Create("/hello/burger")
157+
assert.Nil(t, err)
158+
_, err = writer.Create("/hello/../../burger")
159+
assert.Nil(t, err)
160+
_, err = writer.Create("sample/burger")
161+
assert.Nil(t, err)
162+
_, err = writer.Create(".git/test")
163+
assert.Nil(t, err)
164+
}
165+
120166
func TestJVMCloneCommand(t *testing.T) {
121167
dir, err := os.MkdirTemp("", "")
122168
assert.Nil(t, err)

0 commit comments

Comments
 (0)