summaryrefslogtreecommitdiffstats
path: root/piolium/final-audit-report.md
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-07-29 02:24:41 +0200
committersalmonik <salmonik@tuta.io>2026-07-29 02:24:41 +0200
commitc654a6d17eb58adbb15b9c47ab32bcc3a1666307 (patch)
tree545544bf7d805254415da787fad1cdc711767833 /piolium/final-audit-report.md
parentAdd per-instance mod management with client-side detection (diff)
downloadminecraft-ui-c654a6d17eb58adbb15b9c47ab32bcc3a1666307.tar.gz
minecraft-ui-c654a6d17eb58adbb15b9c47ab32bcc3a1666307.zip
Security audit fixes: patch 16 vulnerabilities across 7 source files
CRITICAL: - Instance name path traversal (AP-001): sanitize::sanitize_instance_name() strips .., /, \, \0, spaces, special chars at all 12 join call sites - Zip-slip protection in world import: starts_with() guard after enclosed_name() HIGH: - RCON command injection: validate_username() rejects non-MC usernames across all 6 player action macros (whitelist, op, ban) - Level-seed properties injection: sanitize_seed() strips \n \r = : \0 - CSRF protection: SameSite=Lax -> SameSite=Strict on session cookie MEDIUM: - Session TTL: server-side 24h expiry via strftime check in require_auth - Rate limiting: in-memory 10-ip/5min sliding window on login - Background task stale is_active: all queries use concrete WHERE id=?1 - Mod validation DoS: 500MB cap, 10k class scan limit, 10k CP entry cap LOW: - Logout auth guard: moved into protected route group + CurrentUser param - Mod orphan race: DB insert before file write - Backup orphan race: DB insert before ZIP creation - Template fix: broken Askama == comparisons in edit.html All fixes compile clean with zero warnings. 10 unit tests pass.
Diffstat (limited to '')
-rw-r--r--piolium/final-audit-report.md407
1 files changed, 407 insertions, 0 deletions
diff --git a/piolium/final-audit-report.md b/piolium/final-audit-report.md
new file mode 100644
index 0000000..049d2b2
--- /dev/null
+++ b/piolium/final-audit-report.md
@@ -0,0 +1,407 @@
1# Security Audit Report: salmon/minecraft-ui
2
3=========================================
4
5## Executive Summary
6
7This audit of **minecraft-ui** — a self-hosted Rust (axum) web application that manages Docker-based Minecraft server instances — identified **17 validated vulnerabilities** spanning path traversal, injection, CSRF, session management, authorization, concurrency, denial-of-service, and cryptographic weaknesses. The most critical issue is **arbitrary filesystem access via unsanitized instance names** (AP-001), which enables path-traversal-driven directory creation, deletion, and constrained file read/write across 12 confirmed code paths — including 4 variant instances discovered in Phase 12. Four high-severity findings were cold-verified via adversarial review (P11). Combined with universal CSRF absence (31 POST endpoints) and a flat authorization model, the application provides minimal defense-in-depth: any authenticated user can destroy data, modify server configurations, or gain persistent access to Minecraft server consoles. The audit reached draft stage but the **findings promotion pipeline stalled** — no PoCs were built and no `piolium/findings/` directory was created. This report is assembled from available draft, chamber, and knowledge-base artifacts.
8
9## Methodology Summary
10
11- **Intelligence Gathering:** Advisory collection via `cargo-audit-advisory` (SBOM), architecture inventory of 16 Rust source files, dependency analysis (rusqlite, bollard, multer, zip)
12- **Knowledge Base:** Threat modeling with DFD/CFD slices (P3), manual attack surface inventory of 38 routes (P8), domain attack research (Minecraft RCON, Java .properties, Docker env injection)
13- **Static Analysis:** Structural extraction via manual code review; CodeQL database could not be built (system constraint); Semgrep ran but with limited Rust rule coverage
14- **Review Chambers:** 6-cluster multi-agent debate system (path-traversal, injection, auth-session, state-concurrency, denial-of-service, security-architecture). 37 findings from P4/P5/P6/P8 reviewed → **17 VALID** survivors, 7 FALSE POSITIVE, 8 DROP, 5 DUPLICATE
15- **Verification:** P11 cold verification (adversarial review) for 4 highest-severity findings: p10-001 (CONFIRMED), p10-003 (CONFIRMED), p10-004 (DISPROVED), p10-005 (CONFIRMED with severity downgrade challenge)
16- **Variant Analysis (P12):** 4 path-traversal variants discovered from AP-001 root cause search
17
18## Summary of Findings
19
20| ID | Title | Severity | PoC Status | Status |
21|----|-------|----------|------------|--------|
22| — | Instance Name Path Traversal (p10-001) | CRITICAL | draft-only | Not promoted |
23| — | Level-Seed Properties Injection (p10-003) | HIGH | draft-only | Not promoted |
24| — | Missing CSRF Protection (p10-005) | HIGH | draft-only | Not promoted |
25| — | RCON Password Exposed to All Users (p10-004) | **LOW** (DISPROVED) | blocked | Adversarial reversal |
26| — | RCON Command Injection (p10-002) | MEDIUM | draft-only | Not promoted |
27| — | Flat Authorization Model (p10-010) | MEDIUM | draft-only | Not promoted |
28| — | No Server-Side Session TTL (p10-006) | MEDIUM | draft-only | Not promoted |
29| — | No Rate Limiting Login (p10-007) | MEDIUM | draft-only | Not promoted |
30| — | Background Task Stale is_active (p10-011) | MEDIUM | draft-only | Not promoted |
31| — | Delete-Create Name Reuse Race (p10-012) | MEDIUM | draft-only | Not promoted |
32| — | No Idempotency (p10-013) | MEDIUM | draft-only | Not promoted |
33| — | Mod Validation Denial of Service (p10-016) | MEDIUM | draft-only | Not promoted |
34| — | No Encryption at Rest (p10-017) | MEDIUM | draft-only | Not promoted |
35| — | Logout No Auth Middleware (p10-008) | LOW | draft-only | Not promoted |
36| — | Cookie No Secure Flag (p10-009) | LOW | draft-only | Not promoted |
37| — | Mod Write Before DB Orphan (p10-014) | LOW | draft-only | Not promoted |
38| — | Backup Orphan Race (p10-015) | LOW | draft-only | Not promoted |
39
40### Variant Findings (Phase 12)
41
42| Variant ID | Title | Severity | Parent | PoC Status |
43|-----------|-------|----------|--------|------------|
44| p12-001 | World Import Path Traversal | HIGH | p10-001 | draft-only |
45| p12-002 | Regenerate World Path Traversal | HIGH | p10-001 | draft-only |
46| p12-003 | Player Management Path Traversal | MEDIUM | p10-001 | draft-only |
47| p12-004 | Backup Create Path Traversal | MEDIUM | p10-001 | draft-only |
48
49> **Note:** No findings were promoted to `piolium/findings/` with PoC scripts, evidence, or full report.md files. All entries above remain at draft stage in `piolium/findings-draft/`.
50
51---
52
53## Technical Findings Detail
54
55### Instance Name Path Traversal (p10-001 — CRITICAL equivalent)
56
57- **Severity:** CRITICAL
58- **Summary:** The instance `name` field flows unsanitized into `Path::join()` for 8 different filesystem operations. Rust's `Path::join()` follows `..` components, enabling arbitrary directory creation, deletion, and constrained file read/write outside the intended data directory.
59- **Impact:** An authenticated attacker can:
60 - **Delete arbitrary directories** via `remove_dir_all` (path: `src/routes/instances.rs:388-392`) — e.g., name=`../../../target` deletes the project build directory
61 - **Create arbitrary directories** via `create_dir_all` (path: `src/routes/instances.rs:204-206`)
62 - **Write files to arbitrary locations** (constrained by `/mods/` or `/data/world/` suffix chaining via mod upload and world import)
63 - **Read files from arbitrary locations** (constrained by world export and backup download paths)
64- **Root Cause:** `Path::join()` in Rust follows `..` components. User-controlled `form.name` is passed directly with no sanitization, length limits, or character restrictions. No validation exists at any of the 12 known join call sites.
65- **Key Code Reference:** `src/routes/instances.rs:204-206` — `Path::join(&form.name)` → `create_dir_all`
66- **PoC Status:** draft-only (no executable PoC built)
67- **Detailed Report:** `piolium/findings-draft/p10-001-instance-name-path-traversal.md`
68- **Adversarial Review:** `piolium/adversarial-reviews/p10-001-instance-name-path-traversal-review.md` — CONFIRMED, severity challenge rejected
69
70#### Attack Pattern: AP-001
71
72This finding is the root of attack pattern **AP-001** (Path Traversal via Unsanitized Instance Name), which has 12 confirmed instances across 4 route modules:
73- `src/routes/instances.rs:205` (create_dir_all)
74- `src/routes/instances.rs:392` (remove_dir_all)
75- `src/routes/mods.rs:126` (mods dir creation)
76- `src/routes/mods.rs:343` (mod rescan)
77- `src/routes/mods.rs:394` (mod delete)
78- `src/routes/backups.rs:107` (backup path)
79- `src/routes/instances.rs:593` (world export)
80- `src/routes/instances.rs:739` (server.properties)
81- `src/routes/instances.rs:672` (world import — variant)
82- `src/routes/instances.rs:776` (regenerate world — variant)
83- `src/routes/players.rs:53` (player management — variant)
84- `src/routes/backups.rs:112` (backup create — variant)
85
86#### Variants
87
88| Variant ID | Title | Severity | Location | Flow |
89|-----------|-------|----------|----------|------|
90| p12-001 | World Import Path Traversal | HIGH | `instances.rs:672` | `instance_name` from DB → `world_dir.join(zip_entry)` → `File::create()` |
91| p12-002 | Regenerate World Path Traversal | HIGH | `instances.rs:776` | `instance_name` from DB → `.join(&name)` → `remove_dir_all(world_dir)` |
92| p12-003 | Player Management Path Traversal | MEDIUM | `players.rs:53` | `inst_name` → `.join(...)` → `read_json_list()` (read-only, 3 filenames) |
93| p12-004 | Backup Create Path Traversal | MEDIUM | `backups.rs:112` | `name` → `{name}_{timestamp}.zip` → `.join(&filename)` → `File::create()` |
94
95Variant details: `piolium/findings-draft/p12-001-*.md` through `piolium/findings-draft/p12-004-*.md`
96
97---
98
99### Level-Seed Properties Injection (p10-003 — HIGH)
100
101- **Severity:** HIGH
102- **Summary:** The `POST /instances/{id}/world/regenerate` handler writes the user-supplied `seed` value into `server.properties` via line-based replacement with no escaping. Newline characters in the seed inject arbitrary Java `.properties` entries.
103- **Impact:** Persistent modification of Minecraft server configuration:
104 - Set `online-mode=false` (disable authentication — any player can join as anyone)
105 - Set `enforce-whitelist=false` (bypass whitelist restrictions)
106 - Change difficulty, gamemode, max-players, PvP settings
107 - Inject malformed properties causing server startup failure (DoS)
108 - **Persistence:** Injected values survive across server restarts until manually cleaned
109- **Root Cause:** `format!("level-seed={seed}")` writes the seed value directly into `server.properties` without escaping. The Java `.properties` spec treats newlines as property separators. The `properties.rs:13-19` reader also lacks escape-sequence processing (spec gap G1).
110- **Key Code Reference:** `src/routes/instances.rs:715-759` — `regenerate_world` handler, line replacement loop
111- **PoC Status:** draft-only
112- **Detailed Report:** `piolium/findings-draft/p10-003-level-seed-properties-injection.md`
113- **Adversarial Review:** `piolium/adversarial-reviews/p10-003-level-seed-properties-injection-review.md` — CONFIRMED, severity unchanged
114
115---
116
117### Missing CSRF Protection (p10-005 — HIGH)
118
119- **Severity:** HIGH (adversarial challenge to MEDIUM rejected)
120- **Summary:** The application has no CSRF protection across any of its 31 POST endpoints. No CSRF tokens are generated or validated. No Origin/Referer header validation exists. The session cookie uses `SameSite=Lax` which permits cookies on top-level cross-site POST navigations.
121- **Impact:** Universal cross-site request forgery enabling:
122 - **Account takeover:** Cross-site password change (though `current_password` IS required for `/change-password`, the superuser `/accounts/set-password` does NOT require the current password)
123 - **Instance destruction:** Cross-site delete requests wipe server data
124 - **File system manipulation:** CSRF + path traversal (p10-001) to write files to arbitrary locations
125 - **Minecraft server compromise:** CSRF to op attackers on the Minecraft server via player management endpoints
126 - **Malicious mod upload:** Cross-site mod upload writes JAR files to server
127- **Root Cause:** Cookie `SameSite=Lax` (not `Strict`) and zero CSRF token infrastructure. No axum CSRF middleware, no custom token generation, no header validation.
128- **Key Code Reference:** `src/auth.rs:83-86` — Cookie with `SameSite=Lax`; entire `src/routes/mod.rs` — no CSRF middleware
129- **PoC Status:** draft-only
130- **Detailed Report:** `piolium/findings-draft/p10-005-missing-csrf-protection.md`
131- **Adversarial Review:** `piolium/adversarial-reviews/p10-005-missing-csrf-protection-review.md` — CONFIRMED; severity down-challenge from HIGH to MEDIUM rejected by chamber (sub-claim D partially false but overall impact remains HIGH)
132
133---
134
135### RCON Command Injection (p10-002 — MEDIUM)
136
137- **Severity:** MEDIUM
138- **Summary:** The `player_action!` macro in `src/routes/players.rs` constructs RCON commands by interpolating user-supplied usernames via `format!()` without sanitization. Six player management endpoints are affected.
139- **Impact:** Operation-target manipulation via space injection, silent operation failure from malformed usernames. In vanilla Minecraft, RCON does not support command chaining (no `;` or `&&` injection), limiting impact to argument injection. On Spigot/Paper servers with command-chaining plugins, broader injection may be possible.
140- **Root Cause:** `format!("whitelist add {}", form.username)` — no validation, no character filtering, no Minecraft username format enforcement.
141- **Key Code Reference:** `src/routes/players.rs:89-102` — `player_action!` macro; `PlayerAction.username` is a raw `String`
142- **PoC Status:** draft-only
143- **Detailed Report:** `piolium/findings-draft/p10-002-rcon-command-injection.md`
144
145---
146
147### Flat Authorization Model (p10-010 — MEDIUM)
148
149- **Severity:** MEDIUM
150- **Summary:** Any authenticated user has full access to ALL instances, mods, backups, and player operations. There is no per-resource ownership, no role granularity beyond binary superuser/non-superuser, and no instance-level authorization.
151- **Impact:** In multi-user deployments, every user is a full administrator of every server instance. Data exfiltration, destructive operations, and Minecraft server control are all available to any authenticated account.
152- **Root Cause:** No `owner_id` column on `instances` table; all handlers use `CurrentUser(_user)` with destructured-and-ignored user variable; all queries lack user-scoped filters.
153- **Key Code References:** `src/routes/instances.rs` (all handlers), `src/routes/players.rs` (`player_action!`), `src/routes/backups.rs`, `src/routes/mods.rs`
154- **PoC Status:** draft-only
155- **Detailed Report:** `piolium/findings-draft/p10-010-flat-authorization-model.md`
156
157---
158
159### No Server-Side Session TTL (p10-006 — MEDIUM)
160
161- **Severity:** MEDIUM
162- **Summary:** The `require_auth` middleware validates session cookies against the database but never checks the `created_at` timestamp, despite the column existing in the schema. Stolen session cookies remain valid indefinitely server-side.
163- **Root Cause:** `WHERE s.id = ?1` query at `src/auth.rs:108-115` lacks a time-based filter. Cookie Max-Age=86400 is client-side only and trivially bypassed.
164- **Key Code Reference:** `src/auth.rs:108-115` — session query without `created_at` filter
165- **PoC Status:** draft-only
166- **Detailed Report:** `piolium/findings-draft/p10-006-no-server-side-session-ttl.md`
167
168---
169
170### No Rate Limiting Login (p10-007 — MEDIUM)
171
172- **Severity:** MEDIUM
173- **Summary:** `POST /login` has no rate limiting, account lockout, or progressive delay. Argon2id (~100ms/attempt) provides a weak mitigating factor.
174- **Root Cause:** No rate-limiting middleware, no `governor` or equivalent crate in Cargo.toml.
175- **Key Code Reference:** `src/auth.rs:39-92` — authenticate handler; `src/routes/mod.rs:44` — route registration
176- **PoC Status:** draft-only
177- **Detailed Report:** `piolium/findings-draft/p10-007-no-rate-limiting-login.md`
178
179---
180
181### Background Task Stale is_active (p10-011 — MEDIUM)
182
183- **Severity:** MEDIUM
184- **Summary:** `activate_instance` spawns a background tokio task that updates `container_state` using `WHERE is_active = 1` instead of the concrete instance ID. If the user switches active instances during the 60-second polling window, the stale task writes to the wrong instance's state.
185- **Root Cause:** 5 UPDATE statements at `src/routes/instances.rs:457-502` all use `WHERE is_active = 1` instead of `WHERE id = ?1`.
186- **Key Code Reference:** `src/routes/instances.rs:457-502` — background tokio task
187- **PoC Status:** draft-only (requires dynamic test)
188- **Detailed Report:** `piolium/findings-draft/p10-011-background-task-stale-is-active.md`
189
190---
191
192### Delete-Create Name Reuse Race (p10-012 — MEDIUM)
193
194- **Severity:** MEDIUM
195- **Summary:** `delete_instance` releases the DB mutex before `remove_dir_all`. A concurrent `create_instance` with the same name can create a new instance whose data directory is then wiped by the still-running deletion.
196- **Root Cause:** Mutex released at `drop(conn)` between `DELETE FROM instances` and `remove_dir_all()` (microsecond-to-millisecond race window).
197- **Key Code Reference:** `src/routes/instances.rs:360-396`
198- **PoC Status:** draft-only (requires dynamic test)
199- **Detailed Report:** `piolium/findings-draft/p10-012-delete-create-name-reuse-race.md`
200
201---
202
203### No Idempotency (p10-013 — MEDIUM)
204
205- **Severity:** MEDIUM
206- **Summary:** Zero idempotency infrastructure across all 31 POST endpoints. Network request replay (HTMX retry, proxy retry, rapid clicks) causes duplicate operations.
207- **Impact:** Duplicate mod uploads cause classloader conflicts on server restart (DoS). Duplicate backup creation wastes disk space. Duplicate player RCON commands are mostly harmless.
208- **Root Cause:** No idempotency key table, no deduplication logic, no request ID storage.
209- **Key Code Reference:** All POST endpoints in `src/routes/*.rs`
210- **PoC Status:** draft-only (static hypothesis)
211- **Detailed Report:** `piolium/findings-draft/p10-013-no-idempotency.md`
212
213---
214
215### Mod Validation Denial of Service (p10-016 — MEDIUM)
216
217- **Severity:** MEDIUM
218- **Summary:** `validate_mod()` parses uploaded JAR constant pools with no timeout or resource limits. A crafted constant pool (cp_count=65535, expensive CONSTANT_Utf8 entries) causes CPU exhaustion on the async runtime.
219- **Impact:** Async thread pool exhaustion; multiple concurrent crafted uploads make the server unresponsive.
220- **Root Cause:** Unbounded `while i < cp_count` loop at `src/mods.rs:173-232` with no timeout wrapping.
221- **Key Code Reference:** `src/mods.rs:173-232` — `scan_single_class()`; `src/routes/mods.rs:109-250` — no timeout around `validate_mod`
222- **PoC Status:** draft-only
223- **Detailed Report:** `piolium/findings-draft/p10-016-mod-validation-denial-of-service.md`
224
225---
226
227### No Encryption at Rest (p10-017 — MEDIUM)
228
229- **Severity:** MEDIUM
230- **Summary:** SQLite database `mcui.db` is stored unencrypted on disk with plaintext RCON passwords. Disclosure via prerequisite file read (p10-001 path traversal) or physical access exposes all secrets.
231- **Root Cause:** `Connection::open(path)` at `src/db.rs:16` with no encryption (no SQLCipher, no individual field encryption).
232- **Key Code Reference:** `src/db.rs:16` — `Connection::open(path)`
233- **PoC Status:** draft-only
234- **Detailed Report:** `piolium/findings-draft/p10-017-no-encryption-at-rest.md`
235
236---
237
238### Logout No Auth Middleware (p10-008 — LOW)
239
240- **Severity:** LOW
241- **Summary:** `POST /logout` is registered outside the `require_auth` protected router group. Any unauthenticated request can reach the logout handler. Requires prior session ID disclosure (UUIDv4, 122-bit entropy) for practical exploitation.
242- **Key Code Reference:** `src/routes/mod.rs:20-33` — logout registered before `.merge(protected)`
243- **PoC Status:** draft-only
244- **Detailed Report:** `piolium/findings-draft/p10-008-logout-no-auth-middleware.md`
245
246---
247
248### Cookie No Secure Flag (p10-009 — LOW)
249
250- **Severity:** LOW
251- **Summary:** Session cookie lacks `Secure` flag. With localhost-bound traffic behind an HTTPS-terminating reverse proxy, the cookie travels unencrypted between proxy and app.
252- **Key Code Reference:** `src/auth.rs:83-86` — cookie string missing `; Secure`
253- **PoC Status:** draft-only
254- **Detailed Report:** `piolium/findings-draft/p10-009-cookie-no-secure-flag.md`
255
256---
257
258### Mod Write Before DB Orphan (p10-014 — LOW)
259
260- **Severity:** LOW
261- **Summary:** `process_jar_upload` writes the mod file to disk before inserting the DB record. A crash between these operations orphans the file (invisible to UI, never cleaned up).
262- **Key Code Reference:** `src/routes/mods.rs:234-260`
263- **PoC Status:** draft-only (static hypothesis)
264- **Detailed Report:** `piolium/findings-draft/p10-014-mod-write-before-db-orphan.md`
265
266---
267
268### Backup Orphan Race (p10-015 — LOW)
269
270- **Severity:** LOW
271- **Summary:** `create_backup` creates the ZIP file before inserting the DB record. Concurrent instance deletion during ZIP creation causes a silently-swallowed FK violation, leaving orphaned ZIP files on disk.
272- **Key Code Reference:** `src/routes/backups.rs:85-139`
273- **PoC Status:** draft-only (requires dynamic test)
274- **Detailed Report:** `piolium/findings-draft/p10-015-backup-orphan-race.md`
275
276---
277
278## Attack Surface Summary
279
280The complete attack surface inventory is documented at:
281
282| Artifact | Path | Description |
283|----------|------|-------------|
284| **Knowledge Base Report** | `piolium/attack-surface/knowledge-base-report.md` | Full architecture model, DFD/CFD slices, trust boundaries, component inventory (18 sections) |
285| **Attack Pattern Registry** | `piolium/attack-pattern-registry.json` | 5 confirmed attack patterns (AP-001 through AP-005) with 12+32+1+31+1=77 total confirmed instances |
286| **Manual Attack Surface Inventory** | `piolium/attack-surface/manual-attack-surface-inventory.md` | 38 HTTP routes catalogued with entry points, sinks, trust boundaries |
287| **Source-Sink Flow Paths** | `piolium/attack-surface/source-sink-flows-all-severities.md` | All data flow paths from attacker input to dangerous sinks |
288| **Unauthenticated Surface** | `piolium/attack-surface/unauthenticated-surface.md` | Routes accessible without authentication |
289| **Spec Gap Summary** | `piolium/attack-surface/spec-gap-summary.md` | RFC/contract gaps (Java .properties, Argon2, RCON protocol, Axum contracts) |
290| **Variant Analysis Summary** | `piolium/attack-surface/variant-summary.md` | Phase 12 variant search results |
291| **State/Concurrency Summary** | `piolium/attack-surface/state-concurrency-summary.md` | Race conditions, TOCTOU, ordering bugs |
292| **Advisory Summary** | `piolium/attack-surface/advisory-summary.md` | External advisory intelligence |
293| **SBOM** | `piolium/attack-surface/sbom.json` | Software bill of materials |
294| **Patch Bypass Summary** | `piolium/attack-surface/patch-bypass-summary.md` | Prior-sec patch regression analysis |
295
296### Key Attack Surface Dimensions
297
2981. **38 HTTP routes** — 3 public POST, 1 public GET, 31 authenticated POST, 3 authenticated GET
2992. **5 attacker-controlled input sources** — form fields (instance name, seed, username, motd), multipart uploads (JAR/ZIP files), path parameters (instance ID, backup ID, mod ID), cookie header, outbound Mojang API response
3003. **4 dangerous sinks** — filesystem (create_dir_all, remove_dir_all, File::create, read_to_string), RCON TCP (send_command_async), Docker Unix socket (bollard API), SQLite (rusqlite)
3014. **3 trust boundaries** — unauthenticated→authenticated (session cookie), webUI→filesystem (path traversal), webUI→RCON/Minecraft (command injection)
302
303---
304
305## Coverage Gaps
306
307### Pipeline Failure: Findings Never Promoted
308
309The most significant gap is that **the findings promotion pipeline terminated prematurely** between Phase 12 (variant analysis) and Phase 15 (report assembly):
310
311- `piolium/findings/` — **does not exist** — no finding was ever promoted from draft
312- No PoC scripts were built for any finding
313- No `report.md` files were generated with structured severity/PoC/evidence sections
314- No execution evidence was collected
315- Only 4 of 17 findings received adversarial review (P11 cold verification)
316- No `metadata.json` files were created for variant-parent tracking
317- Validating script (`validate_phase_output.py`) not present at expected path
318
319### Static Analysis Gaps
320
321- **CodeQL database could not be built** — the Rust analyzer version mismatch prevented database construction. Only structural extraction (call graphs, entry points, sinks) was performed from manual review.
322- **Semgrep Pro** not available — cross-file taint analysis was not performed for Rust
323- **No automated sink-to-source tracing** — all data flow mapping was manual
324
325### Multi-User Deployment Not Analyzed for Scale
326
327- The flat authorization model (p10-010) was assessed as MEDIUM based on single-user assumptions
328- In a multi-user deployment (2+ users), the severity of p10-010 + p10-001 + p10-005 escalates to CRITICAL
329- No instance-level access control, audit logging, or rate limiting for user actions
330
331### Encryption & Key Management
332
333- No encryption at rest (p10-017)
334- RCON passwords stored in plaintext
335- No TLS termination handled by the application (delegated to reverse proxy)
336- Session IDs stored in unencrypted SQLite
337
338### Supply Chain Not Scanned
339
340- 19 Rust crate dependencies listed in SBOM but no automated vulnerability scan (cargo-audit not integrated)
341- Outbound Mojang API calls not constrained (no TLS pinning, no timeout documented)
342
343---
344
345## Methodology Notes
346
347### Chamber Workspace Summary
348
349The Phase 10 adversarial review chamber processed 37 finding candidates across 6 clusters:
350
351| Cluster | Attack Class | Candidates | Valid Survivors | Rejected |
352|---------|-------------|-----------|-----------------|----------|
353| path-traversal | Path Traversal & File System | 7 | 1 (H-01) | 6 |
354| injection | Injection (RCON, Docker, Properties) | 5 | 2 (H-08, H-10) | 3 |
355| auth-session | Auth & Session Management | 9 | 4 (H-13, H-14, H-16, H-17) | 5 |
356| state-concurrency | State & Concurrency | 6 | 5 | 1 |
357| denial-of-service | Denial of Service | 4 | 1 (H-28) | 3 |
358| security-architecture | Security Architecture | 6 | 1 (H-33) | 5 |
359| **Total** | | **37** | **17** | **20** |
360
361**Rejection breakdown:** 7 FALSE POSITIVE, 8 DROP, 5 DUPLICATE
362
363### Cold Verification (P11)
364
3654 findings subjected to adversarial review:
366- **p10-001** (Instance Name Path Traversal): CONFIRMED — severity HIGH→HIGH (no change)
367- **p10-003** (Level-Seed Properties Injection): CONFIRMED — severity HIGH→HIGH (no change)
368- **p10-004** (RCON Password Exposed): DISPROVED — password never rendered in edit.html template (Askama explicit-field model)
369- **p10-005** (Missing CSRF Protection): CONFIRMED — severity HIGH→MEDIUM challenged, rejected by chamber (CSRF+chain attacks warrant HIGH)
370
371### Variant Analysis (P12)
372
3734 new variant instances discovered from AP-001 root cause search:
374- All 4 come from instance name path traversal pattern
375- Zero variants found for the remaining 13 findings
376- The path traversal pattern (AP-001) is the most pervasive vulnerability class with 12 total confirmed instances
377
378### Attack Pattern Registry
379
3805 attack patterns documented in `piolium/attack-pattern-registry.json`:
381- AP-001: Path Traversal via Unsanitized Instance Name (12 instances)
382- AP-002: RCON Command Injection via Unsanitized Username (6 instances)
383- AP-003: Java Properties Injection via Unsanitized Seed Value (1 instance)
384- AP-004: Missing CSRF Protection (31 endpoints)
385- AP-005: No Server-Side Session TTL Enforcement (1 query)
386
387---
388
389## Conclusion
390
391This audit catalogued 17 validated vulnerabilities across the minecraft-ui codebase. The most severe class — **path traversal via unsanitized instance names** — creates a systemic risk: any authenticated user can read, write, and delete files anywhere the webUI process can access. The absence of CSRF protection (31 endpoints) and per-resource authorization means that a single compromised account (or a cross-site request from a victim's browser) grants full control over all server instances, their files, and their Minecraft consoles.
392
393The application's security posture is appropriate _only_ for its documented single-user, localhost-only deployment model. Any deployment that:
394- Exposes the WebUI beyond localhost
395- Adds a second user account
396- Sits behind a reverse proxy without CSRF middleware at the proxy layer
397- Does not validate instance names at the input layer
398
399...faces unacceptable risk of data loss, privilege escalation, and persistent compromise.
400
401**Pipeline note:** The audit's findings-draft→findings promotion failed. The 17 validated findings, 4 variants, and 5 attack patterns documented in this report are derived from draft-level analysis without confirmed PoC execution. A follow-up audit should focus on building working PoCs for the critical and high-severity findings and executing them against a deployed instance to confirm exploitability and impact in a real environment.
402
403---
404
405## Deferred Findings (triage skip)
406
407*No findings were triaged to `piolium/findings-deferred/`. The `piolium/findings-deferred/` directory does not exist because no findings were promoted past the draft stage. All 17 validated findings remain at investigative (draft) status.* \ No newline at end of file