mirror of
https://github.com/Corfirean/coa-server-manager.git
synced 2026-11-11 03:51:01 +00:00
13 KiB
13 KiB
Release & Security Hardening Audit (Phase 15)
Version: 0.7.0-rc1
Status: Pre-Release Freeze & Hardening Audit
Target Branch: feat/portable-characters
Date: October 2026
1. Executive Summary & Architecture Freeze
Phase 15 represents the final engineering stabilization and security hardening phase prior to the public release of CoA Server Manager.
The functional architecture is strictly frozen:
- Realm Registry v2 (discovery, signed adverts, capabilities)
- Coordinator & Noise XX authenticated control channel
- Automatic account provisioning & credential linking
- Portable Characters & Remote Portable Transfer
- Direct Ingress (Host proxy, UPnP IGD, NAT-PMP, external reachability verification)
- Game Relay fallback (
coa-relaymultiplexed TCP tunnel) - Real Ascension client launch & realmlist redirection
- Integrated Server Browser & "Play with Friends" tabbed UX
The objective is to verify and prove that the system is:
\text{Correct} + \text{Secure} + \text{Recoverable} + \text{Non-Destructive} + \text{Clean-Installable} + \text{Diagnosable} = \mathbf{Release\ Candidate}
2. Comprehensive Subsystem Security & State Map
| Subsystem | Trust Boundary | Secrets Handled | Persistent State | Network Input | Size / Rate Limits | Failure Mode | Recovery Behavior | Risk Classification |
|---|---|---|---|---|---|---|---|---|
| 1. Manager UI & Tauri Commands | Local user desktop to Tauri backend IPC | None exposed to frontend; passwords handled only as ephemeral strings | Frontend settings, local UI preferences | IPC payloads via Tauri invoke | Strict input schemas; validated paths & credentials | Command returns structured UiError | Frontend displays actionable error modal/banner | P1: Ensure no secret leakage in IPC serialization or error logs |
| 2. Portable Owner Store | Local player process to SQLite DB | None (game character snapshots only) | portable.sqlite (canonical character snapshots, revisions, history) |
None (local SQLite) | SQLite transaction sizes bounded to character JSON (< 2 MiB) | Transaction rollback | WAL journal recovery on restart; corrupt DB fails closed with diagnostic error | P1: Prevent silent deletion of unmigrated/corrupt DB; atomic migrations |
| 3. Portable Host Store | Host Manager process to SQLite DB | Host session state, player session tokens (ephemeral) | portable_host.sqlite (active player sessions, baseline snapshots) |
Controlled by Noise session handler | Bounded by max concurrent sessions (default 64) | Session abort | Server restart cleans stale sessions; canonical state remains safe on Owner | P1: WorkerThreads dependency must fail closed with explicit preflight check |
| 4. SecretStore (Player & Credentials) | Local OS user to persistent storage | Player Ed25519 private key, per-realm game account passwords | .dpapi files (Windows) or 0600 files (Unix) |
None (local storage) | Key names <= 96 bytes, alphanumeric + ._- |
DPAPI decryption failure (e.g. machine change) | Actionable error; fails closed; never generates silent replacement identity | P1: Must be strictly verified and audited for zero memory/log exposure |
| 5. Realm KeyStore (Host Realm Identity) | Local Host Manager to persistent storage | Realm Ed25519 signing private key | Formerly {realm}.key file; migrating to DPAPI |
None (local storage) | 32-byte Ed25519 seed | Decryption/load failure | Fails closed; NEVER silently regenerates RealmId behind user's back | P0/P1: Move from plaintext ACL file to DPAPI SecretStore with migration |
| 6. Registry Client | Host/Player Manager to Public Registry HTTP API | None (signs with Realm Ed25519; reads public listings) | Cached listings, publication registration record | HTTP responses from https://coa-manager.duckdns.org |
Max listing response 4 MiB; 100 entries per page | Network timeout / Registry HTTP error | Exponential backoff retry; Host marks registration unconfirmed | P1: Strict response parser hardening against hostile JSON |
| 7. Coordinator Client & Host Hub | Public Internet WebSocket to Coordinator service | Noise XX handshake (ephemeral Curve25519, static Ed25519) | Active control connections | WebSocket text / binary frames | Rate-limited hello (60/min); max frame 64 KiB | WebSocket disconnect | Automatic reconnect with exponential backoff; active sessions abort cleanly | P1: Hostile frame reassembly and parser hardening |
| 8. Noise XX Control Protocol | Player Manager to Host Manager peer channel | Ephemeral keys, symmetric ChaCha20-Poly1305 keys | None (in-memory cipher state) | Encrypted transport frames | Strict 4 KiB limit on standard control messages | Decryption error / MAC failure | Immediate connection drop; zero state mutation | P1: Adversarial fuzz testing for truncated/corrupt/tampered frames |
| 9. Remote Transfer Flow | Player Manager to Host Manager authenticated channel | Transfer tokens (ephemeral UUID), character payload | Transfer staging directory | TransferOffer, TransferChunk, TransferStatus |
4 KiB chunks, 4 MiB total payload limit; 30s timeout | Chunk checksum failure / timeout | Offer rejected or transaction aborted; rollback staging files | P1: Strict bounded chunk allocations; verify zero character corruption |
| 10. Game Relay Client & Ingress Tunnel | Host Manager / Player Manager to Public Relay VPS | Allocation token, Host auth signature | Active TCP tunnels | Multiplexed TunnelMsg (Auth & World) |
Bounded buffer queues (256 KiB); backpressure drop | Relay disconnect | Player client disconnects; new JOIN requests fall back or retry | P1: Prevent arbitrary localhost/LAN port forwarding; strictly 3724 & 8085 |
| 11. DirectIngress (Host Proxy) | Internet player TCP to Host local Auth/World | None (game packet proxy) | Listening TCP ports | Raw TCP stream (CMD_REALM_LIST) | 8 KiB buffer bounds; 500ms read timeout loops | Ingress worker socket error | Client disconnects cleanly; next JOIN automatically uses Relay | P1: Ensure CMD_REALM_LIST rewrite strictly uses verified external port |
| 12. UPnP IGD Discovery & Mapping | Host Manager to LAN Gateway (SSDP/SOAP) | None | Active port mapping leases | SSDP UDP responses, SOAP HTTP XML | Local LAN IPs only; strict XML tag extraction | Device timeout / mapping refused | Fall back to NAT-PMP or Relay; transactional cleanup on partial failure | P1: Transactional mapping (auth+world); lease renewal; clean removal |
| 13. NAT-PMP Discovery & Mapping | Host Manager to Default IPv4 Gateway | None | Active port mapping leases | NAT-PMP UDP binary packets | Default OS gateway only; bounded port response | Gateway timeout / unsupported | Fall back to UPnP or Relay; periodic lease renewal (3600s) | P1: OS default gateway routing check; transactional cleanup |
| 14. Client realmlist.wtf Handling | Player Manager to local game client filesystem | None | realmlist.wtf file state |
Local disk file | Bounded file size (< 64 KiB) | Process crash during active game | Transactional backup file; automatic restoration on next Manager startup | P1: Prevent permanently clobbered realmlist.wtf after crash |
| 15. Server Installation & Update | Host Manager to server directory & packages | None | Manifest files, backups, installation journals | Signed update packages | SHA-256 verification of manifests and packages | Update failure / verification error | Atomic rollback from journal and snapshot; original files preserved | P1: Absolute non-destructive guarantee over existing user servers |
| 16. MySQL Database Access | Host Manager to local/container MySQL server | MySQL root/acore password | acore_auth, acore_characters, acore_world |
TCP 3306/3307 | Parameterized queries only; bounded statement execution | DB unreachable / query error | Error logged; no unconfirmed state recorded | P1: Credentials never logged or dumped in diagnostics |
| 17. RA / World Console Client | Host Manager to worldserver Remote Admin | RA username & password | None (console connection) | TCP 3443 text stream | Line-based ASCII protocol; bounded timeouts (5s) | Worldserver console down | Returns structured Error::Invalid; graceful retry | P1: Never send unvalidated user input to RA console; zero password log |
| 18. VPS PostgreSQL Database | Registry & Relay to VPS PostgreSQL | Dedicated DB user passwords (coa_registry, coa_relay) |
realms, adverts, allocations tables |
Internal Docker network SQL | Parameterized queries; connection pool limits (20) | Database failover / error | 500 Internal Error to client; automatic reconnection | P1: Logical rotating backups; dedicated unprivileged roles |
| 19. VPS Caddy Reverse Proxy | Public Internet (80/443) to VPS internal network | Let's Encrypt TLS private key | ACME certificate storage in persistent volume | Public HTTPS & WSS requests | Admin API disabled (admin off); strict route reverse proxy |
Upstream unreachable | 502 Bad Gateway | P1: Ensure only 8080/8081/8082 routed; internal ports unpublished |
| 20. Registry Service | Public Internet to VPS Registry API | None (verifies Ed25519 signatures of Host adverts) | PostgreSQL realms, adverts |
HTTP JSON POST/GET requests | Rate limiter per IP (120/min); max advert size 64 KiB | DB error / invalid signature | HTTP 400/403/429/500 | P1: Parameterized queries; strict schema parsing; bounded allocations |
| 21. Coordinator Service & Probe | Public Internet to VPS Coordinator WSS & HTTP probe | Ephemeral Curve25519 keys; verifies Ed25519 | Active peer connections in-memory | WebSocket frames; HTTP probe query/JSON | Max 4 ports; rate-limited; forbidden ports blocked | Connection drop / probe timeout | Clean session teardown; error JSON | P0/P1: Probe must only probe requester's source IP; rate limit; block LAN/internal IPs |
| 22. Relay Service | Public Internet to VPS Relay TCP ports (40000-43999) | Host signature over allocation token | In-memory active session multiplexer | TCP streams from Host & Players | Max 2,000 allocations; 256 KiB backpressure buffer | Stream error / slow reader | Session closed; port returned to pool; no memory leak | P1: Non-root UID; cap_drop ALL; read-only rootfs; log rotation |
3. Finding Classification & Action Plan
P0 / P1 Findings (Must Fix in Phase 15)
-
[P0/P1-01] Windows Realm Signing Key Storage:
- Problem: Host realm Ed25519 signing key stored as plaintext base64 file with ACL (
icacls). - Requirement: Move to protected Windows DPAPI via
SecretStorewith domain separation entropy, transactional migration, validation of public key / RealmId, atomic replacement, and fail-closed if corrupt. - Status: Implemented in Task 2.
- Problem: Host realm Ed25519 signing key stored as plaintext base64 file with ACL (
-
[P1-02] Coordinator Probe Abuse Hardening:
- Problem:
/coord/v1/probemust be verified against generic port scanning: only caller's verified source IP tested, X-Forwarded-For spoofing prevented, probe requests rate-limited, private/loopback/multicast IPs rejected, concurrent probe limits enforced. - Status: Implemented in Task 5.
- Problem:
-
[P1-03] Client
realmlist.wtfCrash Recovery:- Problem: If Manager crashes or power is lost while playing,
realmlist.wtfmight retain the temporary override. - Requirement: Create a crash-safe transaction marker file before modification; on Manager startup, check for uncommitted marker and restore original bytes immediately.
- Status: Implemented in Task 14.
- Problem: If Manager crashes or power is lost while playing,
-
[P1-04] CharacterDatabase WorkerThreads Safety Refusal:
- Problem: Runtime portable character session checkpoints require
CharacterDatabase.WorkerThreads = 1. - Requirement: Preflight check must explicitly inspect
worldserver.confand refuse portable hosting with clear instructions ifWorkerThreads != 1. - Status: Implemented in Task 10.
- Problem: Runtime portable character session checkpoints require
-
[P1-05] Secret & Log Redaction Verification:
- Problem: Passwords, tokens, and private keys could accidentally appear in logs, panics, or diagnostics bundles.
- Requirement: Structured redaction helpers, diagnostic bundle sanitizer, and automated integration test asserting zero leak of sentinel secrets.
- Status: Implemented in Tasks 3 & 27.
-
[P1-06] Adversarial Protocol Fuzz / Decoder Hardening:
- Problem: Malformed, oversized, or truncated network inputs must never panic or allocate unbounded memory.
- Requirement: Comprehensive property and fuzz test suite covering Registry v2 JSON, Noise frames, TransferOffer/Chunk, TunnelMsg, REALM_LIST rewriter, and Coordinator frames.
- Status: Implemented in Task 4.
-
[P1-07] VPS Infrastructure Backup & Restore Automation:
- Problem: VPS PostgreSQL metadata needs automated rotating logical dumps (
pg_dump) with retention and atomic completion markers, plus verified test restore. - Status: Implemented in Task 17.
- Problem: VPS PostgreSQL metadata needs automated rotating logical dumps (
P2 Findings (Acceptable Follow-Up / Out of Scope for Phase 15)
- [P2-01] Desktop Keyring on Linux/macOS: Documented weaker
0600file store behavior on non-Windows platforms. (Windows is the primary release target). - [P2-02] Live Mid-Session TCP Migration Direct
\toRelay: When a direct connection dies mid-session, the game TCP stream disconnects normally; the user re-joins and the next session automatically falls back to Relay. Seamless live session migration is architecturally impossible over raw WoW TCP and is not promised. - [P2-03] Native Ascension Login Screen Prefill: Left out of scope to avoid reverse-engineering
GlueConfig.jsonor client memory.