# Threat model (initial)

**Status:** Draft — Phase 0  
**Last updated:** 2026-06-26  
**Scope:** HexaHost GameCloud control plane, workers, node agents, and game containers.

## Assets

- User credentials and sessions
- Node enrollment tokens and mTLS certificates
- Game server world data and backups
- Billing and audit records
- Internal service credentials (database, Redis, S3)

## Trust boundaries

1. Public internet → Web/API (untrusted)
2. API ↔ Node Agent (mutually authenticated)
3. Node Agent → Docker (trusted local host)
4. Game container → network (untrusted, tenant-controlled code)

## Threat catalog

| ID | Threat | Description | Mitigation (planned / partial) | Residual risk |
|----|--------|-------------|-------------------------------|---------------|
| T01 | Malicious registered user | Abuse file upload, API, or quotas | AuthZ on every endpoint, path validation, rate limits, quotas | Medium — requires ongoing abuse monitoring |
| T02 | Compromised mod/plugin file | Malicious JAR in server directory | Server-side install only, checksum validation, optional ClamAV | Medium |
| T03 | Compromised user account | Attacker uses stolen session | 2FA, session revocation, login rate limits, audit log | Low–Medium |
| T04 | Compromised node agent | Attacker controls agent process | mTLS, signed commands, no inbound agent port, cert rotation | Medium |
| T05 | Compromised game container | Escape or lateral movement | Non-privileged containers, dropped caps, seccomp, network isolation | Medium |
| T06 | Stolen agent token | Replay enrollment or impersonate node | One-time enrollment, token rotation, mTLS binding | Low |
| T07 | Replay of lifecycle message | Duplicate start/stop commands | Idempotency keys, generation counters, message IDs | Low |
| T08 | Path traversal | Access files outside server directory | Server-side path normalization, deny `..` and symlinks | Low |
| T09 | ZIP bomb | Decompression DoS via upload | Size, file count, compression ratio limits | Low |
| T10 | Symlink attack | Escape via symlink in archive | Reject symlinks on extract by default | Low |
| T11 | SSRF via resource pack URL | Server fetches internal URLs | URL allowlist, block RFC1918, validate schemes | Medium |
| T12 | Internal port scan from game server | Scan control plane from container | Egress firewall, no host network mode | Low–Medium |
| T13 | Secret exfiltration via logs | Tokens in console or API logs | Structured logging with redaction, no secrets in env dumps | Low |
| T14 | Queue flooding | Enqueue excessive jobs | Per-user rate limits, queue depth alerts | Medium |
| T15 | Start spam | Repeated start requests (join-to-start) | Rate limits, idempotent starts, captcha at edge (Phase 8) | Medium (Phase 8) |
| T16 | Backup manipulation | Tamper with or replace backups | SHA-256 checksums, server-side encryption, immutable S3 policies | Low |
| T17 | Supply-chain attack | Compromised npm/go dependency | Lockfiles, CI audit, SBOM, image scanning | Medium |
| T18 | Manipulated runtime image | Unauthorized Docker image | Digest-pinned images, admin-managed catalog only | Low |
| T19 | DNS takeover | Hijack game subdomain | DNS provider auth, monitoring, short TTL only where needed | Low |
| T20 | WebSocket hijacking | Steal or inject agent channel | mTLS, origin checks, correlation IDs | Low |
| T21 | Tenant isolation failure | User A accesses User B server | Server-side authZ, row-level checks, audit | Critical — must test continuously |

## Out of scope (documented dependencies)

- DDoS mitigation at network edge (external infrastructure)
- Physical host compromise
- Mojang/Microsoft account security

## Next steps

- [ ] STRIDE review per component (Phase 1)
- [ ] Container seccomp/AppArmor profiles (Phase 2)
- [ ] Penetration test before production (Phase 9)
- [ ] `docs/security/container-isolation.md`, `secrets.md`, `data-retention.md`
