github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/scanners/helm/parser/parser_tar.go (about)

     1  package parser
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"compress/gzip"
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  	"io/fs"
    11  	"os"
    12  	"path/filepath"
    13  
    14  	"github.com/liamg/memoryfs"
    15  
    16  	"github.com/khulnasoft-lab/defsec/pkg/detection"
    17  )
    18  
    19  func (p *Parser) addTarToFS(path string) (fs.FS, error) {
    20  
    21  	var tr *tar.Reader
    22  	var err error
    23  
    24  	tarFS := memoryfs.CloneFS(p.workingFS)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	file, err := tarFS.Open(path)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	defer func() { _ = file.Close() }()
    34  	if detection.IsZip(path) {
    35  		zipped, err := gzip.NewReader(file)
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  		defer func() { _ = zipped.Close() }()
    40  		tr = tar.NewReader(zipped)
    41  	} else {
    42  		tr = tar.NewReader(file)
    43  	}
    44  
    45  	for {
    46  		header, err := tr.Next()
    47  		if err != nil {
    48  			if errors.Is(err, io.EOF) {
    49  				break
    50  			}
    51  			return nil, err
    52  		}
    53  
    54  		// get the individual path and extract to the current directory
    55  		entryPath := header.Name
    56  
    57  		switch header.Typeflag {
    58  		case tar.TypeDir:
    59  			if err := tarFS.MkdirAll(entryPath, os.FileMode(header.Mode)); err != nil {
    60  				return nil, err
    61  			}
    62  		case tar.TypeReg:
    63  			writePath := fmt.Sprintf("%s/%s", filepath.Dir(path), entryPath)
    64  			p.debug.Log("Unpacking tar entry %s", writePath)
    65  			_ = tarFS.MkdirAll(filepath.Dir(writePath), fs.ModePerm)
    66  			content := []byte{}
    67  			writer := bytes.NewBuffer(content)
    68  
    69  			if err != nil {
    70  				return nil, err
    71  			}
    72  			for {
    73  				_, err := io.CopyN(writer, tr, 1024)
    74  				if err != nil {
    75  					if errors.Is(err, io.EOF) {
    76  						break
    77  					}
    78  					return nil, err
    79  				}
    80  			}
    81  
    82  			p.debug.Log("writing file contents to %s", writePath)
    83  			if err := tarFS.WriteFile(writePath, writer.Bytes(), fs.ModePerm); err != nil {
    84  				return nil, err
    85  			}
    86  
    87  		default:
    88  			return nil, fmt.Errorf("could not untar the section")
    89  		}
    90  	}
    91  
    92  	// remove the tarball from the fs
    93  	if err := tarFS.Remove(path); err != nil {
    94  		return nil, err
    95  	}
    96  
    97  	return tarFS, nil
    98  }