mirror of
https://github.com/anchore/syft.git
synced 2026-10-30 22:12:28 +01:00
fix: only extract zip and tar family archives
`identifyFormat` accepted any extractor mholt identified, which put the 7z and rar decoders (`bodgit/sevenzip`, `rardecode`) on untrusted input with no test coverage. Only zip, tar and compressed tar are opened now, until other formats are deliberately supported. This also fixes java resource adapters: a `.rar` that is really a zip used to be identified by name as RAR and fail to extract. An unsupported identification now falls through to the zip end-of-central-directory check, so it's read as the zip it is. Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
@@ -85,17 +85,17 @@ func archiveFileName(archivePath string) string {
|
||||
//
|
||||
// Identification from the head of the stream wins: a tar holding one jar ends in that jar's central
|
||||
// directory, and reading the tar as a zip would lose the rest. The end of the stream is consulted
|
||||
// only when the head identifies nothing, which is how a zip appended to a launcher script (a Spring
|
||||
// Boot executable jar) is found.
|
||||
// only when the head identifies nothing supported, which is how a zip appended to a launcher script (a
|
||||
// Spring Boot executable jar) is found, and how a java resource adapter (a zip named .rar) is read.
|
||||
func identifyFormat(ctx context.Context, name string, content ReaderAtSeeker) archives.Extractor {
|
||||
if _, err := content.Seek(0, io.SeekStart); err != nil {
|
||||
return nil
|
||||
}
|
||||
format, _, err := intFile.IdentifyArchive(ctx, name, content)
|
||||
if err == nil {
|
||||
// a bare compression format, such as a gzipped file that is not a tar, is not extractable
|
||||
extractor, _ := format.(archives.Extractor)
|
||||
return extractor
|
||||
if extractor := supportedExtractor(format); extractor != nil {
|
||||
return extractor
|
||||
}
|
||||
}
|
||||
if HasZipEndOfCentralDirectory(content) {
|
||||
return archives.Zip{}
|
||||
@@ -103,6 +103,24 @@ func identifyFormat(ctx context.Context, name string, content ReaderAtSeeker) ar
|
||||
return nil
|
||||
}
|
||||
|
||||
// supportedExtractor admits only the zip and tar families, the tar family optionally compressed. Other
|
||||
// formats mholt identifies, such as 7z and rar, pull in decoders that have not been exercised against
|
||||
// untrusted input here, so they are not opened until they are deliberately supported. A bare
|
||||
// compression format, such as a gzipped file that is not a tar, is not extractable either.
|
||||
func supportedExtractor(format archives.Format) archives.Extractor {
|
||||
switch f := format.(type) {
|
||||
case archives.Zip:
|
||||
return f
|
||||
case archives.Tar:
|
||||
return f
|
||||
case archives.CompressedArchive:
|
||||
if _, ok := f.Extraction.(archives.Tar); ok {
|
||||
return f
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extract adds every entry of the archive. Reaching the disk limit stops the walk and marks the
|
||||
// resolver truncated rather than failing.
|
||||
func (r *Resolver) extract(ctx context.Context, format archives.Extractor, content ReaderAtSeeker, exclusions Exclusions) error {
|
||||
|
||||
@@ -38,6 +38,11 @@ func Test_identifyFormat(t *testing.T) {
|
||||
{"test.zip", zipBytes(t, sampleFiles), archives.Zip{}},
|
||||
{"test.tar.gz", tarGzBytes(t, sampleFiles), archives.CompressedArchive{}},
|
||||
{"plain.txt", []byte("just text"), nil},
|
||||
// identified by mholt, but not opened until their decoders are deliberately supported
|
||||
{"test.7z", []byte("7z\xbc\xaf\x27\x1c\x00\x04"), nil},
|
||||
{"test.rar", []byte("Rar!\x1a\x07\x01\x00"), nil},
|
||||
// a java resource adapter archive is a zip that shares rar's extension
|
||||
{"adapter.rar", zipBytes(t, sampleFiles), archives.Zip{}},
|
||||
// the name can be claimed by identification, so the probe alone must not admit prose
|
||||
{"app.jar", []byte("plain text, no central directory anywhere in it"), nil},
|
||||
{"bundle", []byte("plain text, no central directory anywhere in it"), nil},
|
||||
|
||||
Reference in New Issue
Block a user