# Security Audit Report: salmon/minecraft-ui ========================================= ## Executive Summary This 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. ## Methodology Summary - **Intelligence Gathering:** Advisory collection via `cargo-audit-advisory` (SBOM), architecture inventory of 16 Rust source files, dependency analysis (rusqlite, bollard, multer, zip) - **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) - **Static Analysis:** Structural extraction via manual code review; CodeQL database could not be built (system constraint); Semgrep ran but with limited Rust rule coverage - **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 - **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) - **Variant Analysis (P12):** 4 path-traversal variants discovered from AP-001 root cause search ## Summary of Findings | ID | Title | Severity | PoC Status | Status | |----|-------|----------|------------|--------| | — | Instance Name Path Traversal (p10-001) | CRITICAL | draft-only | Not promoted | | — | Level-Seed Properties Injection (p10-003) | HIGH | draft-only | Not promoted | | — | Missing CSRF Protection (p10-005) | HIGH | draft-only | Not promoted | | — | RCON Password Exposed to All Users (p10-004) | **LOW** (DISPROVED) | blocked | Adversarial reversal | | — | RCON Command Injection (p10-002) | MEDIUM | draft-only | Not promoted | | — | Flat Authorization Model (p10-010) | MEDIUM | draft-only | Not promoted | | — | No Server-Side Session TTL (p10-006) | MEDIUM | draft-only | Not promoted | | — | No Rate Limiting Login (p10-007) | MEDIUM | draft-only | Not promoted | | — | Background Task Stale is_active (p10-011) | MEDIUM | draft-only | Not promoted | | — | Delete-Create Name Reuse Race (p10-012) | MEDIUM | draft-only | Not promoted | | — | No Idempotency (p10-013) | MEDIUM | draft-only | Not promoted | | — | Mod Validation Denial of Service (p10-016) | MEDIUM | draft-only | Not promoted | | — | No Encryption at Rest (p10-017) | MEDIUM | draft-only | Not promoted | | — | Logout No Auth Middleware (p10-008) | LOW | draft-only | Not promoted | | — | Cookie No Secure Flag (p10-009) | LOW | draft-only | Not promoted | | — | Mod Write Before DB Orphan (p10-014) | LOW | draft-only | Not promoted | | — | Backup Orphan Race (p10-015) | LOW | draft-only | Not promoted | ### Variant Findings (Phase 12) | Variant ID | Title | Severity | Parent | PoC Status | |-----------|-------|----------|--------|------------| | p12-001 | World Import Path Traversal | HIGH | p10-001 | draft-only | | p12-002 | Regenerate World Path Traversal | HIGH | p10-001 | draft-only | | p12-003 | Player Management Path Traversal | MEDIUM | p10-001 | draft-only | | p12-004 | Backup Create Path Traversal | MEDIUM | p10-001 | draft-only | > **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/`. --- ## Technical Findings Detail ### Instance Name Path Traversal (p10-001 — CRITICAL equivalent) - **Severity:** CRITICAL - **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. - **Impact:** An authenticated attacker can: - **Delete arbitrary directories** via `remove_dir_all` (path: `src/routes/instances.rs:388-392`) — e.g., name=`../../../target` deletes the project build directory - **Create arbitrary directories** via `create_dir_all` (path: `src/routes/instances.rs:204-206`) - **Write files to arbitrary locations** (constrained by `/mods/` or `/data/world/` suffix chaining via mod upload and world import) - **Read files from arbitrary locations** (constrained by world export and backup download paths) - **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. - **Key Code Reference:** `src/routes/instances.rs:204-206` — `Path::join(&form.name)` → `create_dir_all` - **PoC Status:** draft-only (no executable PoC built) - **Detailed Report:** `piolium/findings-draft/p10-001-instance-name-path-traversal.md` - **Adversarial Review:** `piolium/adversarial-reviews/p10-001-instance-name-path-traversal-review.md` — CONFIRMED, severity challenge rejected #### Attack Pattern: AP-001 This finding is the root of attack pattern **AP-001** (Path Traversal via Unsanitized Instance Name), which has 12 confirmed instances across 4 route modules: - `src/routes/instances.rs:205` (create_dir_all) - `src/routes/instances.rs:392` (remove_dir_all) - `src/routes/mods.rs:126` (mods dir creation) - `src/routes/mods.rs:343` (mod rescan) - `src/routes/mods.rs:394` (mod delete) - `src/routes/backups.rs:107` (backup path) - `src/routes/instances.rs:593` (world export) - `src/routes/instances.rs:739` (server.properties) - `src/routes/instances.rs:672` (world import — variant) - `src/routes/instances.rs:776` (regenerate world — variant) - `src/routes/players.rs:53` (player management — variant) - `src/routes/backups.rs:112` (backup create — variant) #### Variants | Variant ID | Title | Severity | Location | Flow | |-----------|-------|----------|----------|------| | p12-001 | World Import Path Traversal | HIGH | `instances.rs:672` | `instance_name` from DB → `world_dir.join(zip_entry)` → `File::create()` | | p12-002 | Regenerate World Path Traversal | HIGH | `instances.rs:776` | `instance_name` from DB → `.join(&name)` → `remove_dir_all(world_dir)` | | p12-003 | Player Management Path Traversal | MEDIUM | `players.rs:53` | `inst_name` → `.join(...)` → `read_json_list()` (read-only, 3 filenames) | | p12-004 | Backup Create Path Traversal | MEDIUM | `backups.rs:112` | `name` → `{name}_{timestamp}.zip` → `.join(&filename)` → `File::create()` | Variant details: `piolium/findings-draft/p12-001-*.md` through `piolium/findings-draft/p12-004-*.md` --- ### Level-Seed Properties Injection (p10-003 — HIGH) - **Severity:** HIGH - **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. - **Impact:** Persistent modification of Minecraft server configuration: - Set `online-mode=false` (disable authentication — any player can join as anyone) - Set `enforce-whitelist=false` (bypass whitelist restrictions) - Change difficulty, gamemode, max-players, PvP settings - Inject malformed properties causing server startup failure (DoS) - **Persistence:** Injected values survive across server restarts until manually cleaned - **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). - **Key Code Reference:** `src/routes/instances.rs:715-759` — `regenerate_world` handler, line replacement loop - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-003-level-seed-properties-injection.md` - **Adversarial Review:** `piolium/adversarial-reviews/p10-003-level-seed-properties-injection-review.md` — CONFIRMED, severity unchanged --- ### Missing CSRF Protection (p10-005 — HIGH) - **Severity:** HIGH (adversarial challenge to MEDIUM rejected) - **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. - **Impact:** Universal cross-site request forgery enabling: - **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) - **Instance destruction:** Cross-site delete requests wipe server data - **File system manipulation:** CSRF + path traversal (p10-001) to write files to arbitrary locations - **Minecraft server compromise:** CSRF to op attackers on the Minecraft server via player management endpoints - **Malicious mod upload:** Cross-site mod upload writes JAR files to server - **Root Cause:** Cookie `SameSite=Lax` (not `Strict`) and zero CSRF token infrastructure. No axum CSRF middleware, no custom token generation, no header validation. - **Key Code Reference:** `src/auth.rs:83-86` — Cookie with `SameSite=Lax`; entire `src/routes/mod.rs` — no CSRF middleware - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-005-missing-csrf-protection.md` - **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) --- ### RCON Command Injection (p10-002 — MEDIUM) - **Severity:** MEDIUM - **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. - **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. - **Root Cause:** `format!("whitelist add {}", form.username)` — no validation, no character filtering, no Minecraft username format enforcement. - **Key Code Reference:** `src/routes/players.rs:89-102` — `player_action!` macro; `PlayerAction.username` is a raw `String` - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-002-rcon-command-injection.md` --- ### Flat Authorization Model (p10-010 — MEDIUM) - **Severity:** MEDIUM - **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. - **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. - **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. - **Key Code References:** `src/routes/instances.rs` (all handlers), `src/routes/players.rs` (`player_action!`), `src/routes/backups.rs`, `src/routes/mods.rs` - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-010-flat-authorization-model.md` --- ### No Server-Side Session TTL (p10-006 — MEDIUM) - **Severity:** MEDIUM - **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. - **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. - **Key Code Reference:** `src/auth.rs:108-115` — session query without `created_at` filter - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-006-no-server-side-session-ttl.md` --- ### No Rate Limiting Login (p10-007 — MEDIUM) - **Severity:** MEDIUM - **Summary:** `POST /login` has no rate limiting, account lockout, or progressive delay. Argon2id (~100ms/attempt) provides a weak mitigating factor. - **Root Cause:** No rate-limiting middleware, no `governor` or equivalent crate in Cargo.toml. - **Key Code Reference:** `src/auth.rs:39-92` — authenticate handler; `src/routes/mod.rs:44` — route registration - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-007-no-rate-limiting-login.md` --- ### Background Task Stale is_active (p10-011 — MEDIUM) - **Severity:** MEDIUM - **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. - **Root Cause:** 5 UPDATE statements at `src/routes/instances.rs:457-502` all use `WHERE is_active = 1` instead of `WHERE id = ?1`. - **Key Code Reference:** `src/routes/instances.rs:457-502` — background tokio task - **PoC Status:** draft-only (requires dynamic test) - **Detailed Report:** `piolium/findings-draft/p10-011-background-task-stale-is-active.md` --- ### Delete-Create Name Reuse Race (p10-012 — MEDIUM) - **Severity:** MEDIUM - **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. - **Root Cause:** Mutex released at `drop(conn)` between `DELETE FROM instances` and `remove_dir_all()` (microsecond-to-millisecond race window). - **Key Code Reference:** `src/routes/instances.rs:360-396` - **PoC Status:** draft-only (requires dynamic test) - **Detailed Report:** `piolium/findings-draft/p10-012-delete-create-name-reuse-race.md` --- ### No Idempotency (p10-013 — MEDIUM) - **Severity:** MEDIUM - **Summary:** Zero idempotency infrastructure across all 31 POST endpoints. Network request replay (HTMX retry, proxy retry, rapid clicks) causes duplicate operations. - **Impact:** Duplicate mod uploads cause classloader conflicts on server restart (DoS). Duplicate backup creation wastes disk space. Duplicate player RCON commands are mostly harmless. - **Root Cause:** No idempotency key table, no deduplication logic, no request ID storage. - **Key Code Reference:** All POST endpoints in `src/routes/*.rs` - **PoC Status:** draft-only (static hypothesis) - **Detailed Report:** `piolium/findings-draft/p10-013-no-idempotency.md` --- ### Mod Validation Denial of Service (p10-016 — MEDIUM) - **Severity:** MEDIUM - **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. - **Impact:** Async thread pool exhaustion; multiple concurrent crafted uploads make the server unresponsive. - **Root Cause:** Unbounded `while i < cp_count` loop at `src/mods.rs:173-232` with no timeout wrapping. - **Key Code Reference:** `src/mods.rs:173-232` — `scan_single_class()`; `src/routes/mods.rs:109-250` — no timeout around `validate_mod` - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-016-mod-validation-denial-of-service.md` --- ### No Encryption at Rest (p10-017 — MEDIUM) - **Severity:** MEDIUM - **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. - **Root Cause:** `Connection::open(path)` at `src/db.rs:16` with no encryption (no SQLCipher, no individual field encryption). - **Key Code Reference:** `src/db.rs:16` — `Connection::open(path)` - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-017-no-encryption-at-rest.md` --- ### Logout No Auth Middleware (p10-008 — LOW) - **Severity:** LOW - **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. - **Key Code Reference:** `src/routes/mod.rs:20-33` — logout registered before `.merge(protected)` - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-008-logout-no-auth-middleware.md` --- ### Cookie No Secure Flag (p10-009 — LOW) - **Severity:** LOW - **Summary:** Session cookie lacks `Secure` flag. With localhost-bound traffic behind an HTTPS-terminating reverse proxy, the cookie travels unencrypted between proxy and app. - **Key Code Reference:** `src/auth.rs:83-86` — cookie string missing `; Secure` - **PoC Status:** draft-only - **Detailed Report:** `piolium/findings-draft/p10-009-cookie-no-secure-flag.md` --- ### Mod Write Before DB Orphan (p10-014 — LOW) - **Severity:** LOW - **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). - **Key Code Reference:** `src/routes/mods.rs:234-260` - **PoC Status:** draft-only (static hypothesis) - **Detailed Report:** `piolium/findings-draft/p10-014-mod-write-before-db-orphan.md` --- ### Backup Orphan Race (p10-015 — LOW) - **Severity:** LOW - **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. - **Key Code Reference:** `src/routes/backups.rs:85-139` - **PoC Status:** draft-only (requires dynamic test) - **Detailed Report:** `piolium/findings-draft/p10-015-backup-orphan-race.md` --- ## Attack Surface Summary The complete attack surface inventory is documented at: | Artifact | Path | Description | |----------|------|-------------| | **Knowledge Base Report** | `piolium/attack-surface/knowledge-base-report.md` | Full architecture model, DFD/CFD slices, trust boundaries, component inventory (18 sections) | | **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 | | **Manual Attack Surface Inventory** | `piolium/attack-surface/manual-attack-surface-inventory.md` | 38 HTTP routes catalogued with entry points, sinks, trust boundaries | | **Source-Sink Flow Paths** | `piolium/attack-surface/source-sink-flows-all-severities.md` | All data flow paths from attacker input to dangerous sinks | | **Unauthenticated Surface** | `piolium/attack-surface/unauthenticated-surface.md` | Routes accessible without authentication | | **Spec Gap Summary** | `piolium/attack-surface/spec-gap-summary.md` | RFC/contract gaps (Java .properties, Argon2, RCON protocol, Axum contracts) | | **Variant Analysis Summary** | `piolium/attack-surface/variant-summary.md` | Phase 12 variant search results | | **State/Concurrency Summary** | `piolium/attack-surface/state-concurrency-summary.md` | Race conditions, TOCTOU, ordering bugs | | **Advisory Summary** | `piolium/attack-surface/advisory-summary.md` | External advisory intelligence | | **SBOM** | `piolium/attack-surface/sbom.json` | Software bill of materials | | **Patch Bypass Summary** | `piolium/attack-surface/patch-bypass-summary.md` | Prior-sec patch regression analysis | ### Key Attack Surface Dimensions 1. **38 HTTP routes** — 3 public POST, 1 public GET, 31 authenticated POST, 3 authenticated GET 2. **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 3. **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) 4. **3 trust boundaries** — unauthenticated→authenticated (session cookie), webUI→filesystem (path traversal), webUI→RCON/Minecraft (command injection) --- ## Coverage Gaps ### Pipeline Failure: Findings Never Promoted The most significant gap is that **the findings promotion pipeline terminated prematurely** between Phase 12 (variant analysis) and Phase 15 (report assembly): - `piolium/findings/` — **does not exist** — no finding was ever promoted from draft - No PoC scripts were built for any finding - No `report.md` files were generated with structured severity/PoC/evidence sections - No execution evidence was collected - Only 4 of 17 findings received adversarial review (P11 cold verification) - No `metadata.json` files were created for variant-parent tracking - Validating script (`validate_phase_output.py`) not present at expected path ### Static Analysis Gaps - **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. - **Semgrep Pro** not available — cross-file taint analysis was not performed for Rust - **No automated sink-to-source tracing** — all data flow mapping was manual ### Multi-User Deployment Not Analyzed for Scale - The flat authorization model (p10-010) was assessed as MEDIUM based on single-user assumptions - In a multi-user deployment (2+ users), the severity of p10-010 + p10-001 + p10-005 escalates to CRITICAL - No instance-level access control, audit logging, or rate limiting for user actions ### Encryption & Key Management - No encryption at rest (p10-017) - RCON passwords stored in plaintext - No TLS termination handled by the application (delegated to reverse proxy) - Session IDs stored in unencrypted SQLite ### Supply Chain Not Scanned - 19 Rust crate dependencies listed in SBOM but no automated vulnerability scan (cargo-audit not integrated) - Outbound Mojang API calls not constrained (no TLS pinning, no timeout documented) --- ## Methodology Notes ### Chamber Workspace Summary The Phase 10 adversarial review chamber processed 37 finding candidates across 6 clusters: | Cluster | Attack Class | Candidates | Valid Survivors | Rejected | |---------|-------------|-----------|-----------------|----------| | path-traversal | Path Traversal & File System | 7 | 1 (H-01) | 6 | | injection | Injection (RCON, Docker, Properties) | 5 | 2 (H-08, H-10) | 3 | | auth-session | Auth & Session Management | 9 | 4 (H-13, H-14, H-16, H-17) | 5 | | state-concurrency | State & Concurrency | 6 | 5 | 1 | | denial-of-service | Denial of Service | 4 | 1 (H-28) | 3 | | security-architecture | Security Architecture | 6 | 1 (H-33) | 5 | | **Total** | | **37** | **17** | **20** | **Rejection breakdown:** 7 FALSE POSITIVE, 8 DROP, 5 DUPLICATE ### Cold Verification (P11) 4 findings subjected to adversarial review: - **p10-001** (Instance Name Path Traversal): CONFIRMED — severity HIGH→HIGH (no change) - **p10-003** (Level-Seed Properties Injection): CONFIRMED — severity HIGH→HIGH (no change) - **p10-004** (RCON Password Exposed): DISPROVED — password never rendered in edit.html template (Askama explicit-field model) - **p10-005** (Missing CSRF Protection): CONFIRMED — severity HIGH→MEDIUM challenged, rejected by chamber (CSRF+chain attacks warrant HIGH) ### Variant Analysis (P12) 4 new variant instances discovered from AP-001 root cause search: - All 4 come from instance name path traversal pattern - Zero variants found for the remaining 13 findings - The path traversal pattern (AP-001) is the most pervasive vulnerability class with 12 total confirmed instances ### Attack Pattern Registry 5 attack patterns documented in `piolium/attack-pattern-registry.json`: - AP-001: Path Traversal via Unsanitized Instance Name (12 instances) - AP-002: RCON Command Injection via Unsanitized Username (6 instances) - AP-003: Java Properties Injection via Unsanitized Seed Value (1 instance) - AP-004: Missing CSRF Protection (31 endpoints) - AP-005: No Server-Side Session TTL Enforcement (1 query) --- ## Conclusion This 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. The application's security posture is appropriate _only_ for its documented single-user, localhost-only deployment model. Any deployment that: - Exposes the WebUI beyond localhost - Adds a second user account - Sits behind a reverse proxy without CSRF middleware at the proxy layer - Does not validate instance names at the input layer ...faces unacceptable risk of data loss, privilege escalation, and persistent compromise. **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. --- ## Deferred Findings (triage skip) *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.*