diff --git a/pkg/mining/manager.go b/pkg/mining/manager.go index 7a7dc24..2b35d7c 100644 --- a/pkg/mining/manager.go +++ b/pkg/mining/manager.go @@ -212,6 +212,13 @@ func (m *Manager) StartMiner(minerType string, config *Config) (Miner, error) { return nil, fmt.Errorf("a miner with a similar configuration is already running: %s", instanceName) } + // Validate user-provided HTTPPort if specified + if config.HTTPPort != 0 { + if config.HTTPPort < 1024 || config.HTTPPort > 65535 { + return nil, fmt.Errorf("HTTPPort must be between 1024 and 65535, got %d", config.HTTPPort) + } + } + apiPort, err := findAvailablePort() if err != nil { return nil, fmt.Errorf("failed to find an available port for the miner API: %w", err) @@ -471,8 +478,17 @@ func (m *Manager) GetMinerHashrateHistory(name string) ([]HashratePoint, error) return miner.GetHashrateHistory(), nil } -// Stop stops the manager and its background goroutines. +// Stop stops all running miners, background goroutines, and closes resources. func (m *Manager) Stop() { + // Stop all running miners first + m.mu.Lock() + for name, miner := range m.miners { + if err := miner.Stop(); err != nil { + log.Printf("Warning: failed to stop miner %s: %v", name, err) + } + } + m.mu.Unlock() + close(m.stopChan) m.waitGroup.Wait() diff --git a/pkg/mining/node_service.go b/pkg/mining/node_service.go index d71b007..d2b06e6 100644 --- a/pkg/mining/node_service.go +++ b/pkg/mining/node_service.go @@ -3,6 +3,7 @@ package mining import ( "encoding/json" "net/http" + "strconv" "github.com/Snider/Mining/pkg/node" "github.com/gin-gonic/gin" @@ -407,8 +408,8 @@ func (ns *NodeService) handleRemoteLogs(c *gin.Context) { minerName := c.Param("miner") lines := 100 if l := c.Query("lines"); l != "" { - if _, err := c.GetQuery("lines"); err { - // Use default + if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 { + lines = parsed } } diff --git a/pkg/mining/service.go b/pkg/mining/service.go index 4c34583..f5e33ee 100644 --- a/pkg/mining/service.go +++ b/pkg/mining/service.go @@ -81,7 +81,25 @@ func NewService(manager ManagerInterface, listenAddr string, displayAddr string, // After calling InitRouter, you can use the Router field directly as an http.Handler. func (s *Service) InitRouter() { s.Router = gin.Default() - s.Router.Use(cors.Default()) + + // Configure CORS to only allow local origins + corsConfig := cors.Config{ + AllowOrigins: []string{ + "http://localhost:4200", // Angular dev server + "http://127.0.0.1:4200", + "http://localhost:9090", // Default API port + "http://127.0.0.1:9090", + "http://localhost:" + strings.Split(s.Server.Addr, ":")[len(strings.Split(s.Server.Addr, ":"))-1], + "http://127.0.0.1:" + strings.Split(s.Server.Addr, ":")[len(strings.Split(s.Server.Addr, ":"))-1], + "wails://wails", // Wails desktop app + }, + AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, + AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization"}, + ExposeHeaders: []string{"Content-Length"}, + AllowCredentials: true, + MaxAge: 12 * time.Hour, + } + s.Router.Use(cors.New(corsConfig)) s.SetupRoutes() } @@ -207,6 +225,8 @@ func (s *Service) updateInstallationCache() (*SystemInfo, error) { switch availableMiner.Name { case "xmrig": miner = NewXMRigMiner() + case "tt-miner": + miner = NewTTMiner() default: continue } @@ -265,6 +285,8 @@ func (s *Service) handleUpdateCheck(c *gin.Context) { switch availableMiner.Name { case "xmrig": miner = NewXMRigMiner() + case "tt-miner": + miner = NewTTMiner() default: continue } @@ -360,6 +382,8 @@ func (s *Service) handleInstallMiner(c *gin.Context) { switch minerType { case "xmrig": miner = NewXMRigMiner() + case "tt-miner": + miner = NewTTMiner() default: c.JSON(http.StatusBadRequest, gin.H{"error": "unknown miner type"}) return diff --git a/pkg/mining/ttminer_start.go b/pkg/mining/ttminer_start.go index ac0bdbb..3416da2 100644 --- a/pkg/mining/ttminer_start.go +++ b/pkg/mining/ttminer_start.go @@ -58,6 +58,7 @@ func (m *TTMiner) Start(config *Config) error { } if err := m.cmd.Start(); err != nil { + stdinPipe.Close() return fmt.Errorf("failed to start TT-Miner: %w", err) } @@ -131,6 +132,33 @@ func addTTMinerCliArgs(config *Config, args *[]string) { // Add any extra arguments passed via CLIArgs if config.CLIArgs != "" { extraArgs := strings.Fields(config.CLIArgs) - *args = append(*args, extraArgs...) + for _, arg := range extraArgs { + // Skip potentially dangerous arguments + if isValidCLIArg(arg) { + *args = append(*args, arg) + } else { + log.Printf("Warning: skipping invalid CLI argument: %s", arg) + } + } } } + +// isValidCLIArg validates CLI arguments to prevent injection or dangerous patterns +func isValidCLIArg(arg string) bool { + // Block shell metacharacters and dangerous patterns + dangerousPatterns := []string{";", "|", "&", "`", "$", "(", ")", "{", "}", "<", ">", "\n", "\r"} + for _, p := range dangerousPatterns { + if strings.Contains(arg, p) { + return false + } + } + // Block arguments that could override security-related settings + blockedArgs := []string{"--api-access-token", "--api-worker-id"} + lowerArg := strings.ToLower(arg) + for _, blocked := range blockedArgs { + if strings.HasPrefix(lowerArg, blocked) { + return false + } + } + return true +} diff --git a/pkg/mining/xmrig_start.go b/pkg/mining/xmrig_start.go index 441759f..e11febf 100644 --- a/pkg/mining/xmrig_start.go +++ b/pkg/mining/xmrig_start.go @@ -81,6 +81,7 @@ func (m *XMRigMiner) Start(config *Config) error { } if err := m.cmd.Start(); err != nil { + stdinPipe.Close() return err }