ax(node): remove banned fmt import from bundle.go
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

Replace all fmt.Errorf calls in bundle.go with ProtocolError structs,
eliminating the banned fmt import. Error messages are preserved via
string concatenation consistent with the rest of the node package.

Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
Claude 2026-04-02 17:10:07 +01:00
parent ec0ab317ea
commit 70fc8a6552
No known key found for this signature in database
GPG key ID: AF404715446AEB41

View file

@ -6,7 +6,6 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
@ -51,14 +50,14 @@ func CreateProfileBundle(profileJSON []byte, name string, password string) (*Bun
// Create a TIM with just the profile config
timContainer, err := tim.New()
if err != nil {
return nil, fmt.Errorf("failed to create TIM: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create TIM: " + err.Error()}
}
timContainer.Config = profileJSON
// Encrypt to STIM format
stimData, err := timContainer.ToSigil(password)
if err != nil {
return nil, fmt.Errorf("failed to encrypt bundle: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to encrypt bundle: " + err.Error()}
}
// Calculate checksum
@ -91,7 +90,7 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo
// Read miner binary
minerData, err := os.ReadFile(minerPath)
if err != nil {
return nil, fmt.Errorf("failed to read miner binary: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to read miner binary: " + err.Error()}
}
// Create a tarball with the miner binary
@ -99,19 +98,19 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo
filepath.Base(minerPath): minerData,
})
if err != nil {
return nil, fmt.Errorf("failed to create tarball: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create tarball: " + err.Error()}
}
// Create DataNode from tarball
dataNode, err := datanode.FromTar(tarData)
if err != nil {
return nil, fmt.Errorf("failed to create datanode: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create datanode: " + err.Error()}
}
// Create TIM from DataNode
timContainer, err := tim.FromDataNode(dataNode)
if err != nil {
return nil, fmt.Errorf("failed to create TIM: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create TIM: " + err.Error()}
}
// Set profile as config if provided
@ -122,7 +121,7 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo
// Encrypt to STIM format
stimData, err := timContainer.ToSigil(password)
if err != nil {
return nil, fmt.Errorf("failed to encrypt bundle: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to encrypt bundle: " + err.Error()}
}
checksum := calculateChecksum(stimData)
@ -140,7 +139,7 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo
func ExtractProfileBundle(bundle *Bundle, password string) ([]byte, error) {
// Verify checksum first
if calculateChecksum(bundle.Data) != bundle.Checksum {
return nil, fmt.Errorf("checksum mismatch - bundle may be corrupted")
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "checksum mismatch - bundle may be corrupted"}
}
// If it's unencrypted JSON, just return it
@ -151,7 +150,7 @@ func ExtractProfileBundle(bundle *Bundle, password string) ([]byte, error) {
// Decrypt STIM format
timContainer, err := tim.FromSigil(bundle.Data, password)
if err != nil {
return nil, fmt.Errorf("failed to decrypt bundle: %w", err)
return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to decrypt bundle: " + err.Error()}
}
return timContainer.Config, nil
@ -162,25 +161,25 @@ func ExtractProfileBundle(bundle *Bundle, password string) ([]byte, error) {
func ExtractMinerBundle(bundle *Bundle, password string, destDir string) (string, []byte, error) {
// Verify checksum
if calculateChecksum(bundle.Data) != bundle.Checksum {
return "", nil, fmt.Errorf("checksum mismatch - bundle may be corrupted")
return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "checksum mismatch - bundle may be corrupted"}
}
// Decrypt STIM format
timContainer, err := tim.FromSigil(bundle.Data, password)
if err != nil {
return "", nil, fmt.Errorf("failed to decrypt bundle: %w", err)
return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to decrypt bundle: " + err.Error()}
}
// Convert rootfs to tarball and extract
tarData, err := timContainer.RootFS.ToTar()
if err != nil {
return "", nil, fmt.Errorf("failed to convert rootfs to tar: %w", err)
return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to convert rootfs to tar: " + err.Error()}
}
// Extract tarball to destination
minerPath, err := extractTarball(tarData, destDir)
if err != nil {
return "", nil, fmt.Errorf("failed to extract tarball: %w", err)
return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to extract tarball: " + err.Error()}
}
return minerPath, timContainer.Config, nil
@ -264,7 +263,7 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
// Ensure destDir is an absolute, clean path for security checks
absDestDir, err := filepath.Abs(destDir)
if err != nil {
return "", fmt.Errorf("failed to resolve destination directory: %w", err)
return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to resolve destination directory: " + err.Error()}
}
absDestDir = filepath.Clean(absDestDir)
@ -289,13 +288,13 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
// Reject absolute paths
if filepath.IsAbs(cleanName) {
return "", fmt.Errorf("invalid tar entry: absolute path not allowed: %s", header.Name)
return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "invalid tar entry: absolute path not allowed: " + header.Name}
}
// Reject paths that escape the destination directory
parentPrefix := ".." + string(os.PathSeparator)
if bytes.HasPrefix([]byte(cleanName), []byte(parentPrefix)) || cleanName == ".." {
return "", fmt.Errorf("invalid tar entry: path traversal attempt: %s", header.Name)
return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "invalid tar entry: path traversal attempt: " + header.Name}
}
// Build the full path and verify it's within destDir
@ -305,7 +304,7 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
// Final security check: ensure the path is still within destDir
destDirPrefix := absDestDir + string(os.PathSeparator)
if !bytes.HasPrefix([]byte(fullPath), []byte(destDirPrefix)) && fullPath != absDestDir {
return "", fmt.Errorf("invalid tar entry: path escape attempt: %s", header.Name)
return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "invalid tar entry: path escape attempt: " + header.Name}
}
switch header.Typeflag {
@ -334,7 +333,7 @@ func extractTarball(tarData []byte, destDir string) (string, error) {
}
if written > maxFileSize {
os.Remove(fullPath)
return "", fmt.Errorf("file %s exceeds maximum size of %d bytes", header.Name, maxFileSize)
return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "file " + header.Name + " exceeds maximum allowed size"}
}
// Track first executable