# Secure Local Payload Validation End-to-end validation of a forged AetherForge agent **without risking production keys or your daily driver**. This playbook recommends one primary path and tiered alternatives. --- ## Verdict: Docker Windows vs Disposable VM | Environment | Server | Linux agent | Windows agent (full payload) | |-------------|--------|-------------|------------------------------| | **Host + Hyper-V VM** (recommended) | ✅ `devrun.bat` on host | ✅ optional WSL2 VM | ✅ real Win32, WMI, USB, desktop, GPU | | **Linux Docker** | ✅ Go binary in container | ✅ partial C2 + mining | ❌ cannot compile/run Windows agent features | | **Docker Desktop Windows containers** | ⚠️ awkward (Server Core image) | N/A | ❌ **poor fit** — see below | ### Why not Docker Windows for full payload tests? Windows containers run on **Windows Server Core** (or similar) with a different kernel contract than desktop Windows: - **No interactive desktop** — screenshots, clipboard, and many PowerShell UI calls fail or return empty. - **WMI USB subscriptions, autorun.inf, LNK spread, Defender tampering** — require desktop-class Windows and often admin on a real session. - **GPU mining (T-Rex / TeamRedMiner)** — no practical NVIDIA/AMD passthrough in Windows containers. - **USB propagation** — container cannot see host removable drives the way a VM or bare metal can. - **WinRM / SMB lateral spread** — needs a multi-machine lab network, not an isolated container namespace. **Honest recommendation:** use **Docker/Linux only for server + automated CI**. For **full Windows payload validation**, use a **disposable Hyper-V (or VMware) Windows 10/11 VM** — or a dedicated second physical “burner” PC — then **revert a snapshot** when done. --- ## Tiered Test Matrix ### Tier 0 — Mining stack only (no C2, no payload) Proves RandomX + pool worker + optional live Stratum **on the dev machine**. ```powershell cd agent go run ./cmd/mine-validate -seconds 20 -threads 2 ``` | Validates | Does not validate | |-----------|-------------------| | RandomX engine, pool workers, live pool login | C2 WebSocket, forge bake, persistence, spread | > **Note:** `mine-validate` may spam `[miner] hash error: randomx VM not initialized` during the multi-threaded pool phase while still reporting non-zero H/s and exiting 0. Treat non-zero hashrate + exit 0 as pass; investigate if exit code is 1. ### Tier 1 — Automated CI (no real agent) ```bat test.bat ``` Or faster (skip builds + Playwright): ```powershell .\scripts\test-suite.ps1 -SkipBuild -SkipE2E ``` | Phase | Coverage | |-------|----------| | Go server + agent unit/integration tests | API, forge, auth, pool, fusion | | Vitest | Dashboard forms, preflight, offline gating | | Playwright (`-SkipE2E` off) | Login smoke, mocked fleet UI | Also with server already running: ```powershell .\scripts\smoke-test.ps1 -BaseUrl http://127.0.0.1:8989 ``` ### Tier 2 — Server + Linux agent (same host, Linux VM, or Docker) Good for **C2 path**, basic recon, mining install, systemd persistence — **not** Windows-only ops. **Option A — Docker (isolated bridge, recommended for CI)** ```bash # Automated proof (compose up + assert + teardown) scripts/ci-docker-mining.sh # Linux / macOS / GHA .\scripts\ci-docker-mining.ps1 # Windows + Docker Desktop ``` Or interactive: ```bash docker compose -f docker/docker-compose.yml up --build ``` - Server on host port **18989**; dashboard `testuser` / `testpass` (see `docker/data/users.json`). - Fleet secret `e2e-docker-fleet-secret-fixed001` in `docker/data/config.json` + `docker/agent-builtin.go`. - Test wallet in `docker/data/config.json` and `docker/agent-builtin.go` (see E2E test address in security rules above). - Agent container has **no internet egress** — mines via server-broadcast jobs only. - RandomX is pure Go (`go-randomx`); agent image needs **no CGO**. - **Assert logic:** `GET /api/v1/health` → `GET /api/v1/agents` (Basic auth) finds `status=online` with `hashrate_15s|1m|15m > 0`, or `GET /api/v1/dashboard/stats` shows `online_agents >= 1` and `total_hashrate > 0`. Waits up to **3 minutes**. - GitHub Actions: `.github/workflows/ci-docker-mining.yml` on every push (`ubuntu-latest`). - Verify manually: Fleet Roster shows `docker-e2e-linux`; hashrate fields populate after ~30s. - Teardown: `docker compose -f docker/docker-compose.yml down --rmi local -v` Full notes: [`docker/README.md`](../docker/README.md). **Option B — WSL2 / Linux VM** 1. Start server on host: `devrun.bat` 2. Forge **Linux amd64** worker pointing at `http://:8989` (VM must reach host; bind server to LAN or use Hyper-V Default Switch IP). 3. Run agent in WSL2 or a small Linux VM. 4. Crucible: `sysinfo`, `pause`/`resume`, `get_log`, `list_dir` (Linux file ops). ### Tier 3 — Full Windows payload (primary E2E path) **Topology** ``` ┌─────────────────────────────┐ ┌──────────────────────────────┐ │ Host PC (control) │ LAN │ Disposable Win10/11 VM │ │ devrun.bat → :8989 │◄───────►│ forged test agent.exe │ │ data/ logs, builds, DB │ only │ snapshot "clean" → revert │ └─────────────────────────────┘ └──────────────────────────────┘ ``` **Security rules** 1. **Dedicated test data dir** — e.g. `data-e2e\` with fresh `users.json`; never copy production `data\`. 2. **Test wallet** — use the repo's recommended E2E Monero address (public test wallet, not for production): `85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm` Seeded automatically in `data-e2e/config.json` by `scripts/e2e-validate.ps1` and in `docker/data/config.json` for Tier 2 Docker. Do not use your production wallet. 3. **Rotate fleet secret** after tests if you ever pointed at shared `data\`. 4. **No internet egress from VM** (optional but ideal) — allow only host IP:8989 + pool Stratum if testing live shares. 5. **Snapshot before forge run** — revert VM when finished (“toss the machine”). --- ## Step-by-Step: Tier 3 Playbook ### 1. Prepare isolated server data ```powershell $env:AETHERFORGE_E2E_USER = "testuser" $env:AETHERFORGE_E2E_PASS = "testpass" New-Item -ItemType Directory -Force -Path ".\data-e2e" | Out-Null '{"testuser":"testpass"}' | Set-Content ".\data-e2e\users.json" -Encoding UTF8 ``` Start server against that directory (from repo root): ```bat bin\miner-server.exe -port 8989 -data .\data-e2e ``` Or use `devrun.bat` after pointing `-data` at `data-e2e` (or run `.\scripts\e2e-validate.ps1 -PrepareOnly`). ### 2. Calibrate for validation In **Calibrate** (Settings): | Setting | Test value | |---------|------------| | Server URL | `http://:8989` (must match what the VM can reach) | | Wallet | `85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm` (or match `data-e2e/config.json`) | | `file_logging` | **true** (required for `get_log` / `data-e2e\logs\`) | | Stealth mode | **off** for first pass (easier debugging) | | USB / share / auto-spread | **off** until spread is explicitly under test | | Remote aggressive ops | **on** only in a VM snapshot you will revert | | `agent_kill_after_days` | optional safety fuse (e.g. `1`) | ### 3. Forge a test worker In **Forge**: - Target OS: **Windows amd64** - Worker name: `e2e-validate` - Enable only features you intend to test this session - Download `e2e-validate.exe` + paired `uninstall-e2e-validate.ps1` Or use the orchestrator script (API forge) after server is up: ```powershell .\scripts\e2e-validate.ps1 -ForgeAgent ``` ### 4. Hyper-V VM setup (Windows) ```powershell # Example: Hyper-V Manager or PowerShell # 1. Create Gen2 VM, 4 GB RAM, 40 GB disk # 2. Internal or Default Switch network (host reachable) # 3. Take snapshot named "clean-pre-agent" # 4. Copy forged exe into VM (shared folder or ISO) ``` **Before running the agent:** snapshot name recorded, VM has no personal data, Defender policy acceptable for your lab. ### 5. Run agent in VM 1. Execute forged exe once (install + connect). 2. Confirm agent appears on dashboard **Fleet Roster** (online). 3. Check server console for `[agent] authenticated`. ### 6. Crucible command checklist Run against the test agent. Tick as you go. **Core / mining** - [ ] `sysinfo` — hostname, cores, RAM - [ ] `pause` / `resume` / `restart` — miner control - [ ] `connectivity_probe` — C2 + pool reachability JSON - [ ] `get_log` — tail returns `miner.log` lines **Recon (Windows)** - [ ] `ps`, `netstat`, `listen_ports` - [ ] `ipconfig`, `wifi`, `posture`, `patch_status` - [ ] `screenshot` (needs interactive logged-in desktop) - [ ] `camera_list` / `camera_snapshot` (needs ffmpeg + camera) **Files (Windows)** - [ ] `list_dir` — `C:\Users\\` - [ ] `read_file` — small text file - [ ] `upload` / `download` round-trip **Power / lifecycle** - [ ] `exec` / `powershell` — benign echo command - [ ] `reboot_machine` — only if snapshot revert planned - [ ] `uninstall` or run `uninstall-*.ps1` — M-10 checklist **Advanced (enable in forge + revert snapshot after)** - [ ] `get_wifi_passwords`, `defender_off`, `firewall_*` - [ ] USB spread — second USB passthrough device - [ ] `spread_now` / LAN spread — requires second lab VM ### 7. Collect logs | Source | Path / action | |--------|----------------| | Server stdout | `devrun.bat` window | | Server agent log cache | `data-e2e\logs\.log` | | Agent on disk | `%LOCALAPPDATA%\\miner.log` | | Dashboard | Fleet → Remote Control → **Fetch Log** | | API | `GET /api/v1/agents/{id}/log?refresh=1` | ```powershell Get-ChildItem ".\data-e2e\logs\" Get-Content ".\data-e2e\logs\.log" -Tail 100 ``` ### 8. Teardown (“toss the machine”) 1. **VM:** Hyper-V → **Revert to snapshot** `clean-pre-agent` (or delete VM). 2. **Host:** stop server; archive or delete `data-e2e\` if no longer needed. 3. **Network:** remove any temporary firewall rules allowing VM→host:8989. 4. **Secrets:** if production `data\` was ever used, rotate fleet secret in Calibrate. --- ## Quick orchestration ```powershell # Automated tiers 0–1 + instructions for tier 3 .\scripts\e2e-validate.ps1 # Tier 0 only .\scripts\e2e-validate.ps1 -SkipAutomatedTests -SkipServerCheck # Prepare test data + print checklist (no forge) .\scripts\e2e-validate.ps1 -PrepareOnly ``` --- ## What each existing tool covers | Tool | Tier | Scope | |------|------|-------| | `agent/cmd/mine-validate` | 0 | Mining only | | `test.bat` / `scripts/test-suite.ps1` | 1 | Full automated suite | | `scripts/smoke-test.ps1` | 1 | REST B-01–B-10 | | `scripts/ci-docker-mining.sh` / `.ps1` | 2 | Docker Linux agent hashrate proof | | `.github/workflows/ci-docker-mining.yml` | 2 | GHA push gate | | `server/web/e2e/*.spec.ts` | 1 | Dashboard smoke (mocked WS) | | `docs/TEST_RESULTS.md` | 1–3 | Matrix IDs; M-01–M-09 manual | | `devrun.bat` | 2–3 | Build + launch control server | | Forge + burner VM | 3 | Full payload | --- ## Linux vs Windows agent capabilities (validation scope) | Feature | Windows | Linux | macOS | |---------|---------|-------|-------| | RandomX CPU mining + dashboard hashrate | ✅ | ✅ | ✅ | | GPU RVN mining | ✅ | stub (detect only) | stub | | Screenshot | ✅ (GDI+) | ✅ (scrot/import/gnome-screenshot) | ✅ (screencapture) | | Camera | ✅ (ffmpeg) | ✅ (V4L2/ffmpeg/fswebcam) | stub | | Clipboard | ✅ | ✅ (xclip/pbpaste) | ✅ (pbpaste) | | File browser Crucible | ✅ | ✅ | ✅ | | Posture / syscheck | ✅ (WMI) | ✅ (ufw/systemd/apt) | partial | | Firewall aggressive ops | ✅ (netsh) | ✅ (ufw/iptables) | stub | | USB / WMI spread | ✅ | ❌ | ❌ | | SMB / WinRM spread | ✅ | ❌ | ❌ | | SSH lateral spread | ❌ | ✅ | ✅ | | WiFi password harvest | ✅ | stub | stub | | Defender off | ✅ | N/A (returns error) | N/A | | systemd / LaunchAgent persistence | — | ✅ | ✅ | | Idle-mode mining (CPU % sample) | ✅ | ✅ (fixed: /proc/stat) | ✅ (sysctl kern.cp_time) | Use **Tier 3 Windows VM** when validating spread, GPU, screenshot, or aggressive ops. Use **Tier 2 Linux** for faster C2 regression on recon + mining. --- ## References - Automated test phases: `tests/README.md` - Manual matrix IDs: `docs/TEST_RESULTS.md` (M-01–M-10) - Known gaps: `PROBLEMS.md`