Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61fb52e8f2 |
1 changed files with 25 additions and 15 deletions
|
|
@ -237,15 +237,15 @@ func createTarball(files map[string][]byte) ([]byte, error) {
|
|||
Size: int64(len(content)),
|
||||
}
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return nil, err
|
||||
return nil, coreerr.E("createTarball", "failed to write tar header", err)
|
||||
}
|
||||
if _, err := tw.Write(content); err != nil {
|
||||
return nil, err
|
||||
return nil, coreerr.E("createTarball", "failed to write tar content", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := tw.Close(); err != nil {
|
||||
return nil, err
|
||||
return nil, coreerr.E("createTarball", "failed to close tar writer", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
|
|
@ -261,11 +261,11 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
|
|||
absDestDir = filepath.Clean(absDestDir)
|
||||
|
||||
if err := coreio.Local.EnsureDir(absDestDir); err != nil {
|
||||
return "", err
|
||||
return "", coreerr.E("extractTarball", "failed to ensure destination directory", err)
|
||||
}
|
||||
|
||||
tr := tar.NewReader(bytes.NewReader(tarData))
|
||||
var firstExecutable string
|
||||
var firstExecutablePath string
|
||||
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
|
|
@ -273,7 +273,7 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
|
|||
break
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", coreerr.E("extractTarball", "failed to read tar entry", err)
|
||||
}
|
||||
|
||||
// Security: Sanitize the tar entry name to prevent path traversal (Zip Slip)
|
||||
|
|
@ -301,12 +301,12 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
|
|||
switch hdr.Typeflag {
|
||||
case tar.TypeDir:
|
||||
if err := coreio.Local.EnsureDir(fullPath); err != nil {
|
||||
return "", err
|
||||
return "", coreerr.E("extractTarball", "failed to create directory "+cleanName, err)
|
||||
}
|
||||
case tar.TypeReg:
|
||||
// Ensure parent directory exists
|
||||
if err := coreio.Local.EnsureDir(filepath.Dir(fullPath)); err != nil {
|
||||
return "", err
|
||||
return "", coreerr.E("extractTarball", "failed to create parent directory for "+cleanName, err)
|
||||
}
|
||||
|
||||
// os.OpenFile is used deliberately here instead of coreio.Local.Create/Write
|
||||
|
|
@ -321,18 +321,24 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
|
|||
const maxFileSize int64 = 100 * 1024 * 1024
|
||||
limitedReader := io.LimitReader(tr, maxFileSize+1)
|
||||
written, err := io.Copy(f, limitedReader)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
_ = f.Close()
|
||||
return "", coreerr.E("extractTarball", "failed to write file "+hdr.Name, err)
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return "", coreerr.E("extractTarball", "failed to close extracted file "+hdr.Name, err)
|
||||
}
|
||||
|
||||
if written > maxFileSize {
|
||||
coreio.Local.Delete(fullPath)
|
||||
if err := coreio.Local.Delete(fullPath); err != nil {
|
||||
return "", coreerr.E("extractTarball", "failed to clean up oversized file "+hdr.Name, err)
|
||||
}
|
||||
return "", coreerr.E("extractTarball", "file "+hdr.Name+" exceeds maximum size", nil)
|
||||
}
|
||||
|
||||
// Track first executable
|
||||
if hdr.Mode&0111 != 0 && firstExecutable == "" {
|
||||
firstExecutable = fullPath
|
||||
if hdr.Mode&0111 != 0 && firstExecutablePath == "" {
|
||||
firstExecutablePath = fullPath
|
||||
}
|
||||
// Explicitly ignore symlinks and hard links to prevent symlink attacks
|
||||
case tar.TypeSymlink, tar.TypeLink:
|
||||
|
|
@ -341,13 +347,17 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return firstExecutable, nil
|
||||
return firstExecutablePath, nil
|
||||
}
|
||||
|
||||
// StreamBundle writes a bundle to a writer (for large transfers).
|
||||
func StreamBundle(bundle *Bundle, w io.Writer) error {
|
||||
encoder := json.NewEncoder(w)
|
||||
return encoder.Encode(bundle)
|
||||
if err := encoder.Encode(bundle); err != nil {
|
||||
return coreerr.E("StreamBundle", "failed to encode bundle", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadBundle reads a bundle from a reader.
|
||||
|
|
@ -355,7 +365,7 @@ func ReadBundle(r io.Reader) (*Bundle, error) {
|
|||
var bundle Bundle
|
||||
decoder := json.NewDecoder(r)
|
||||
if err := decoder.Decode(&bundle); err != nil {
|
||||
return nil, err
|
||||
return nil, coreerr.E("ReadBundle", "failed to decode bundle", err)
|
||||
}
|
||||
return &bundle, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue