From c654a6d17eb58adbb15b9c47ab32bcc3a1666307 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 29 Jul 2026 02:24:41 +0200 Subject: 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. --- piolium/attack-surface/advisory-summary.md | 395 +++++++++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 piolium/attack-surface/advisory-summary.md (limited to 'piolium/attack-surface/advisory-summary.md') diff --git a/piolium/attack-surface/advisory-summary.md b/piolium/attack-surface/advisory-summary.md new file mode 100644 index 0000000..eaea57a --- /dev/null +++ b/piolium/attack-surface/advisory-summary.md @@ -0,0 +1,395 @@ +# Advisory Summary: minecraft-ui + +**Generated**: 2025-07-29T01:15:00Z +**Target**: `salmon/minecraft-ui` (self-hosted git at `git.2137697.xyz/salmon/minecraft-ui.git`) +**Analysis scope**: Stage 01 — Intelligence & Dependency Risk + +--- + +## Repository Identity + +| Field | Value | +|---|---| +| OWNER | `salmon` | +| REPO | `minecraft-ui` | +| OWNER_REPO | `salmon/minecraft-ui` | +| Resolution source | `git remote` (`https://git.2137697.xyz/salmon/minecraft-ui.git`) | +| Git history available | Yes (6 commits) | +| GitHub API available | No — self-hosted git server, not github.com | +| Primary ecosystem | Rust (Cargo) — edition 2024 | +| Total lines of code | ~3,213 (Rust source), 6 templates (Askama), 1 CSS, 1 JS (htmx) | + +## Coverage Gaps + +- **Source 1 (git log CVE search)**: No CVE/GHSA references found in repo (0 results) — new project, no changelog, no SECURITY.md +- **Source 2 (GitHub Security Advisories)**: **Skipped** — `gh api` requires github.com; repo lives on `git.2137697.xyz` (self-hosted Gitea/Forgejo) +- **Source 5 (supplementary websearch)**: Not performed — Sources 1, 3, 4 cover all dependency advisories; no project-specific CVEs expected for a new internal tool + +--- + +## Advisory Inventory + +### Direct Dependencies — Vulnerability Status + +All 22 direct dependencies are at versions past all known advisories. No unfixed public vulnerabilities in the direct dependency tree. + +| # | Package | Version | Known Advisories | Affected Range | Current Status | +|---|---------|---------|-----------------|---------------|----------------| +| 1 | `axum` | 0.8.9 | 0 | — | ✅ Clean | +| 2 | `multer` | 3.1.0 | 0 | — | ✅ Clean | +| 3 | `tokio` | 1.52.3 | 5 (historic) | All < 1.38.2 (oldest fix) | ✅ Fixed well above | +| 4 | `rusqlite` | 0.40.1 | 15 (historic) | < 0.25.4 (data races), < 0.26.2 (UAF) | ✅ Fixed well above | +| 5 | `bollard` | 0.17.1 | 2 | Checked — no active vulns | ✅ Clean | +| 6 | `argon2` | 0.5.3 | 0 | — | ✅ Clean | +| 7 | `zip` | 8.6.0 | **1 (CVE-2025-29787)** | 1.3.0 ≤ v < 2.3.0 | ✅ Fixed (v8.6.0 >> fix) | +| 8 | `reqwest` | 0.13.4 | 0 | — | ✅ Clean | +| 9 | `cookie` | 0.18.1 | 2 (historic) | < 0.7.6 | ✅ Fixed well above | +| 10 | `serde` | 1.0.228 | 0 | — | ✅ Clean | +| 11 | `askama` | 0.16.0 | 0 | — | ✅ Clean | +| 12 | `tower-http` | 0.7.0 (+ 0.6.11 transitive) | 2 (historic dir traversal) | < 0.1.3 / < 0.2.1 | ✅ Fixed well above | +| 13 | `axum-extra` | 0.12.6 | 0 | — | ✅ Clean | +| 14 | `tower` | 0.5.3 | 0 | — | ✅ Clean | +| 15 | `chrono` | 0.4.45 | 0 | — | ✅ Clean | +| 16 | `uuid` | 1.23.4 | 0 | — | ✅ Clean | +| 17 | `tempfile` | 3.27.0 | 3 | All historic/pre-2022 | ✅ Clean | +| 18 | `rand` | 0.8.7 | 1 (RUSTSEC-2026-0097) | 0.7.0 ≤ v < 0.8.6 | ✅ Fixed (0.8.7) | +| 19 | `tracing` | 0.1.44 | 1 (RUSTSEC-2023-0078 UAF) | 0.1.38 ≤ v < 0.1.40 | ✅ Fixed (0.1.44) | +| 20 | `serde_json` | 1.0.150 | 0 | — | ✅ Clean | +| 21 | `toml` | 1.1.2 | 0 | — | ✅ Clean | +| 22 | `futures-util` | 0.3.32 | 0 | — | ✅ Clean | + +### Notable Transitive Dependencies + +| Package | Version | Known Advisories | Status | +|---------|---------|-----------------|--------| +| `hyper` | 1.10.1 | 0 | ✅ Clean | +| `h2` | 0.4.15 | 3 (all fixed in 0.4.4+) | ✅ Clean (0.4.15 > 0.4.4) | +| `mio` | 1.2.1 | 0 | ✅ Clean | +| `aes-gcm` | 0.10.3 | 0 | ✅ Clean | + +### Detailed Advisory Records + +#### 1. CVE-2025-29787 — zip crate path traversal (HIGH) + +| Field | Value | +|---|---| +| **ID** | `GHSA-94vh-gphv-8pm8` / `CVE-2025-29787` | +| **Published** | 2025-03-17 | +| **Severity** | HIGH (CVSS:4.0 8.1) | +| **Summary** | `zip` incorrectly canonicalizes paths during archive extraction, leading to arbitrary file write via path traversal | +| **CWEs** | CWE-180 (Incorrect Behavior Order), CWE-22 (Path Traversal), CWE-61 (UNIX Symbolic Link) | +| **Affected** | zip >= 1.3.0, < 2.3.0 | +| **Fixed in** | zip 2.3.0 | +| **Current** | 8.6.0 — **Not affected** | +| **Relevance** | The project uses `zip::ZipArchive` in `mods.rs` (mod extraction from ZIP), `routes/instances.rs` (world import), and `routes/backups.rs` (backup creation). All are using version 8.6.0, past the fix. | + +#### 2. RUSTSEC-2025-0023 — tokio broadcast channel soundness + +| Field | Value | +|---|---| +| **ID** | `GHSA-rr8g-9fpq-6wmg` | +| **Published** | 2025-04-07 | +| **Severity** | Informational (unsoundness) | +| **Summary** | `tokio::sync::broadcast` channel calls `clone` in parallel but does not require `Sync` | +| **Affected** | tokio >= 0.2.5 (various ranges) | +| **Fixed in** | 1.38.2 / 1.43.1 / 1.44.2 | +| **Current** | 1.52.3 — **Not affected** | + +#### 3. RUSTSEC-2024-0332 — h2 CONTINUATION flood (HIGH) + +| Field | Value | +|---|---| +| **ID** | `GHSA-q6cp-qfwq-4gcv` / `RUSTSEC-2024-0332` | +| **Published** | 2024-04-03 | +| **Severity** | HIGH | +| **Summary** | h2 servers vulnerable to degradation of service with CONTINUATION flood frames | +| **Affected** | h2 < 0.3.26 / < 0.4.4 | +| **Fixed in** | 0.4.4 | +| **Current** | 0.4.15 — **Not affected** | + +#### 4. RUSTSEC-2023-0078 — tracing use-after-free + +| Field | Value | +|---|---| +| **ID** | `GHSA-8f24-6m29-wm2r` | +| **Published** | 2024-01-17 | +| **Severity** | Informational | +| **Summary** | Use-after-free in tracing subscriber when `MakeVisitor` is implemented on a type that implements `Visit` without `Clone` | +| **Affected** | tracing >= 0.1.38, < 0.1.40 | +| **Fixed in** | 0.1.40 | +| **Current** | 0.1.44 — **Not affected** | + +--- + +## Vulnerability Pattern Analysis + +### 2a. Component Vulnerability Heatmap + +The project is a **brand-new codebase** with zero first-party CVEs. The heatmap below is derived from dependency advisory history and architectural analysis: + +| Component | Advisory Count (historic) | Risk Factors | Dominant Bug Types | +|-----------|-------------------------|--------------|--------------------| +| **`rusqlite`** | 15 (all historic) | Data races (CVE-2020-35866..73), Use-After-Free (CVE-2021-45713..19) | Race conditions, UAF | +| **`tokio`** | 5 (all historic) | Race conditions, unsoundness | Concurrency bugs | +| **`h2`** (transitive) | 3 (all fixed by 0.4.4) | CONTINUATION flood, DoS | Resource exhaustion | +| **`zip`** | 1 (CVE-2025-29787, fixed in 2.3.0) | Path traversal, symlink | Path traversal | +| **`cookie`** | 2 (both historic, < 0.7.6) | Max-Age DoS, input validation | Input validation | +| **`tempfile`** | 3 (all historic) | Race conditions, permissions | TOCTOU | +| **`rand`** | 1 (RUSTSEC-2026-0097, fixed in 0.8.6) | Unsound with custom logger | Unsoundness | + +**🔥 High-heat components requiring Phase 3/5 attention:** +1. **`mods.rs` (480 lines)** — Custom JAR/ZIP parser, class-file constant pool scanning, ZIP extraction. Highest complexity, most attack surface. +2. **`routes/instances.rs` (782 lines)** — World import/export (ZIP extraction), instance lifecycle, Docker orchestration. Largest single file. +3. **`auth.rs` (199 lines)** — Session management, password hashing, cookie handling. Custom session cookie parsing (no library). +4. **`docker.rs` (209 lines)** — Docker API calls with bollard, container creation with user-controlled env vars. +5. **`rcon.rs` (127 lines)** — Raw TCP protocol implementation, password handling. + +### 2b. Bug Type Recurrence + +| Bug Class | CWEs | Historic Count | Examples | Recurring? | +|-----------|------|---------------|----------|------------| +| **Race condition / TOCTOU** | CWE-362 | 8+ | rusqlite data races, tokio races, tempfile | ⚠️ **Recurring** | +| **Path traversal** | CWE-22 | 2 | zip (CVE-2025-29787), tower-http (RUSTSEC-2022-0043) | ⚠️ **Recurring** | +| **Resource exhaustion / DoS** | CWE-400, CWE-770 | 3 | h2 CONTINUATION flood, cookie Max-Age, h2 general | ⚠️ **Recurring** | +| **Use-after-free** | CWE-416 | 8 | rusqlite UAF, tracing UAF | ⚠️ **Recurring** | +| **Improper input validation** | CWE-20 | 2 | cookie, zip | — | +| **Unsoundness** | — | 2 | tokio broadcast, rand | — | + +**Key insight**: Path traversal recurs across the dependency tree (zip and tower-http). The project's custom ZIP extraction code (`routes/instances.rs:import_world`) should be audited for the same pattern. + +### 2c. Attack Surface Trends + +| Input Vector | Where Exploited | Risk Level | +|-------------|----------------|------------| +| **Uploaded ZIP/JAR files** | `routes/mods.rs`, `routes/instances.rs` (world import) | 🔴 **Critical** | +| **HTTP requests** (form data, multipart) | All routes via axum | 🟡 High | +| **Docker container env vars** | `docker.rs:recreate_container` — user-controlled (version, MOTD, etc.) | 🟡 High | +| **RCON network protocol** | `rcon.rs` — custom TCP implementation | 🟡 High | +| **SQL queries via rusqlite** | All DB operations (uses params! macro — safe) | 🟢 Low | +| **Cookie header parsing** | `auth.rs:require_auth` — manual cookie split | 🟡 Medium | +| **Template rendering** | Askama templates (compile-time, no injection) | 🟢 Low | +| **Config file** | `config.toml` parsed via toml crate | 🟢 Low | + +**Highest-risk attack surface**: The mod upload/validation pipeline (`routes/mods.rs` + `mods.rs`) accepts arbitrary JAR/ZIP uploads with a 500MB size limit and performs custom bytecode-level class scanning. + +### 2d. Patch Quality Signals + +No patch-bypass history exists for this project (new codebase, no patched vulnerabilities). However, several **architectural concerns** warrant attention: + +1. **`mods.rs` class-file scanner** — Custom constant pool parser (not using a library). Any bug in this parser could lead to mis-validation (accepting client-side mods that crash the server, or rejecting valid server mods). No fuzzing evidence exists. + +2. **`auth.rs` cookie session parsing** — Manual `split(';')` + `split_once('=')` parsing of the Cookie header. Equivalent to CWE-172 (Encoding Error). No library cookie parser used despite `cookie` crate being a dependency. + +3. **`docker.rs` env injection** — Instance name, MOTD, version, seed, etc. are directly interpolated into Docker container env vars. No sanitization of values that could contain shell-special characters or newlines (env var injection risk). + +4. **`rcon.rs` packet parsing** — Custom binary protocol parser with `i32::from_le_bytes` length prefix. Potential for integer underflow/overflow in length handling. + +--- + +## Architecture Inventory + +### Components + +| Component | File(s) | Purpose | Security Profile | +|-----------|---------|---------|-----------------| +| **HTTP Router** | `routes/mod.rs` | Axum router with auth middleware | Cookie-based session auth on protected routes | +| **Auth module** | `auth.rs` | Password hashing (Argon2), session creation, login/logout | Custom cookie parsing; sessions in SQLite | +| **Dashboard** | `routes/dashboard.rs` | Landing page showing active instance | Reads-only | +| **Instance Manager** | `routes/instances.rs` | CRUD for server instances, world import/export, activation | World ZIP import/extract; Docker lifecycle | +| **Mod Manager** | `routes/mods.rs`, `mods.rs` | JAR/ZIP upload, validation, class-file scanning | Largest attack surface: custom bytecode parser | +| **Player Manager** | `routes/players.rs` | RCON-based whitelist/OP/ban management | Sends commands via RCON to Minecraft server | +| **Backup Manager** | `routes/backups.rs` | Create/list/restore/download backups | ZIP creation, file read for download | +| **Account Manager** | `routes/accounts.rs` | Account CRUD, password change | Superuser-only; session invalidation on password change | +| **Docker Manager** | `docker.rs` | Container lifecycle via bollard API | Image pull, container create/start/stop with env vars | +| **RCON Client** | `rcon.rs` | Raw TCP RCON protocol implementation | Custom binary protocol parser | +| **Database** | `db.rs` | SQLite via rusqlite with connection pool (Arc) | WAL mode, foreign keys, migrations | +| **Config** | `config.rs` | TOML config loader | Static config, parsed at startup | + +### Transports + +| Transport | Direction | Protocol | Used By | +|-----------|-----------|----------|---------| +| **HTTP** | User ↔ WebUI | HTTP/1.1 (via axum/hyper) | All routes | +| **Docker socket** | WebUI ↔ Docker daemon | Unix socket (bollard) | `docker.rs` | +| **RCON** | WebUI ↔ Minecraft server | TCP, custom binary protocol on port 25575 | `rcon.rs` | +| **Mojang API** | WebUI → piston-meta.mojang.com | HTTPS (reqwest) | Fetching version manifest | +| **File system** | WebUI ↔ Disk | Standard I/O | World export/import, mod uploads, backups | + +### Trust Boundaries + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Internet / LAN │ +│ ┌────────────┐ HTTP :3000 ┌────────────────────────┐ │ +│ │ Browser │ ──────────────▶ │ WebUI (axum) │ │ +│ │ (HTMX/JS) │ │ minecraft-ui process │ │ +│ └────────────┘ │ - auth middleware │ │ +│ │ - cookie sessions │ │ +│ └──────┬─────────────────┘ │ +│ │ │ +│ ┌───────────────────────────────┼──────────────┐ │ +│ │ Docker daemon socket │ RCON TCP │ │ +│ ▼ ▼ │ │ +│ ┌─────────────────────┐ ┌───────────────────┐ │ │ +│ │ Docker Container │ │ Minecraft Server │ │ │ +│ │ itzg/minecraft-srv │ │ (inside Docker) │ │ │ +│ │ port 25565 │ │ port 25575 │ │ │ +│ │ port 25575 │ └───────────────────┘ │ │ +│ └─────────────────────┘ │ │ +│ │ │ +│ ┌────────────────────────────────────────────────────┐ │ │ +│ │ File System │ │ │ +│ │ - server_directory/instances/{name}/data/ │ │ │ +│ │ - server_directory/backups/ │ │ │ +│ │ - server_directory/mcui.db (SQLite) │ │ │ +│ └────────────────────────────────────────────────────┘ │ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Execution Environments + +| Environment | Description | +|-------------|-------------| +| **Host OS** | Linux (presumed — Docker socket, Unix paths) | +| **Rust runtime** | Native binary via `tokio` async runtime | +| **Docker container** | `itzg/minecraft-server` with Java 8/17/21 depending on version | +| **SQLite** | Embedded database (WAL mode) | + +### Highest-Risk Flows (Phase 3 DFD priority) + +1. **Mod Upload → Validation → Disk Write** — External attacker-controlled JAR/ZIP → custom bytecode parser → file written to `mods/` directory +2. **World Import → ZIP Extraction → Disk Write** — Uploaded ZIP → `zip::ZipArchive::by_index` → `enclosed_name()` → file extraction to `world/` +3. **Instance Create → Docker Container Start** — User-controlled form fields → env var interpolation → Docker API call +4. **Backup Download → File Read → HTTP Response** — Backup ID → file read from disk → streamed to user (path traversal risk) +5. **Login → Cookie → Session** — Password verification → session creation → cookie parsing in auth middleware + +--- + +## Component Inventory + +### Runtime + +| Component | Version | Evidence | Security-relevant | +|-----------|---------|----------|-------------------| +| Rust | edition 2024 / stable | `Cargo.toml` | No | + +### Package Dependencies (direct) + +| Component | Version | Purpose | Security-relevant | +|-----------|---------|---------|-------------------| +| axum | 0.8.9 | HTTP framework | Yes — request parsing | +| multer | 3.1.0 | Multipart uploads | Yes — file upload handling | +| tokio | 1.52.3 | Async runtime | Yes — concurrency | +| rusqlite | 0.40.1 | SQLite database | Yes — SQL injection surface | +| bollard | 0.17.1 | Docker API client | Yes — container control | +| argon2 | 0.5.3 | Password hashing | Yes — auth credential handling | +| zip | 8.6.0 | ZIP archive handling | Yes — file extraction | +| reqwest | 0.13.4 | HTTP client | No — version manifest fetches | +| cookie | 0.18.1 | Cookie handling | Yes — session cookies | +| serde | 1.0.228 | Serialization | No | +| askama | 0.16.0 | Template engine | No — compile-time templates | +| tower-http | 0.7.0 | HTTP middleware (static files) | No | +| axum-extra | 0.12.6 | Cookie private jar | Yes — session cookie crypto | +| chrono | 0.4.45 | Date/time | No | +| uuid | 1.23.4 | Session ID generation | No | +| tempfile | 3.27.0 | Temporary files | No | +| rand | 0.8.7 | RNG for passwords | Yes — RCON password generation | +| tracing | 0.1.44 | Logging | No | +| toml | 1.1.2 | Config parsing | No | + +### Binary Dependencies + +| Component | Evidence | Purpose | Security-relevant | +|-----------|----------|---------|-------------------| +| Docker daemon | `bollard::Docker::connect_with_local_defaults()` | Container management | Yes — OS-level access | +| Java (JRE 8/17/21) | Docker `itzg/minecraft-server` images | Minecraft runtime | Yes — runs untrusted mod code | +| `itzg/minecraft-server` | Docker image | Minecraft server packaging | Yes — external image | + +### External Services + +| Service | Evidence | Purpose | Security-relevant | +|---------|----------|---------|-------------------| +| `piston-meta.mojang.com` | `reqwest::get(...)` in `fetch_minecraft_versions()` | Version manifest | No — read-only public API | + +### Datastores + +| Component | Evidence | Purpose | Security-relevant | +|-----------|----------|---------|-------------------| +| SQLite (rusqlite) | `db.rs` | Accounts, sessions, instances, mods | Yes — credential storage | +| Docker volume mounts | `docker.rs` | Minecraft server data | Yes — file system access | +| Server directory | `config.toml:server_directory` | All persistent data | Yes — file system root | + +### Coverage Gaps + +| Category | Status | Note | +|----------|--------|------| +| runtime | ✅ Covered | Rust edition 2024 | +| package | ✅ Covered | All 22 direct deps from Cargo.toml | +| framework | ✅ Covered | axum, askama | +| datastore | ✅ Covered | SQLite, Docker volumes | +| external-service | ✅ Covered | Mojang API | +| container-os | ⚠️ Partial | Dockerfile not in repo; uses `itzg/minecraft-server` images | +| build-ci | ℹ️ None detected | No CI config found in repo | +| binary | ✅ Covered | Docker, Java (via Docker) | +| vendored | ✅ Covered | `static/htmx.min.js` (vendored JS library) | + +--- + +## Dependency Intelligence + +### Security-Relevant Dependencies (derived view) + +| Dependency | Version | Risk Factors | Pattern Cross-Reference | +|-----------|---------|-------------|------------------------| +| **axum** | 0.8.9 | Input parsing, multipart handling | HTTP request surface (2c) | +| **multer** | 3.1.0 | Multipart file upload with 500MB limit | File upload attack surface (2c) | +| **rusqlite** | 0.40.1 | →historic: data races, UAF | Bug class: race conditions (2b) | +| **bollard** | 0.17.1 | Docker socket access, container control | Docker API attack surface (2c) | +| **argon2** | 0.5.3 | Password hashing — credential protection | Auth security (2c) | +| **zip** | 8.6.0 | →historic: path traversal (CVE-2025-29787) | Bug class: path traversal (2b) | +| **cookie** | 0.18.1 | →historic: DoS via Max-Age | Session handling (2c) | +| **axum-extra** | 0.12.6 | Cookie private jar (encryption) | Session security | +| **rand** | 0.8.7 | RCON password generation | Password strength | + +### Key Risk Observations + +1. **No regular dependency scanning configured** — No `cargo audit` or `cargo deny` in CI. Relying on manual version choice. +2. **`htmx.min.js` (vendored)** — Static file served via `tower-http::services::ServeDir`. Should verify integrity of vendored copy. +3. **`itzg/minecraft-server` Docker images** — External base images with Java runtimes. Image pull happens at runtime; no image hash pinning in code. +4. **RCON password generation** — Uses `rand::thread_rng()` (CSPRNG) with 16-char alphanumeric charset (~93 bits entropy). Adequate but no periodic rotation. + +--- + +## Audit Targeting Recommendations + +Based on pattern analysis: + +1. **Phase 3 DFD priorities**: + - **Mod upload/validation pipeline** (`routes/mods.rs` + `mods.rs`) — highest complexity, custom bytecode parser + - **World import/export** (`routes/instances.rs:import_world`, `export_world`) — ZIP extraction to disk + - **Auth middleware** (`auth.rs:require_auth`) — custom cookie parsing without library + +2. **Phase 5 deep probe targets**: + - **Mod validation bypass** — Can a crafted JAR bypass the class-file scanner? (CWE-22, CWE-180) + - **Path traversal in world ZIP extraction** — `zip::ZipArchive::by_index().enclosed_name()` usage + - **Docker env var injection** — User-controlled values in container creation + - **RCON protocol weaknesses** — Integer handling in packet length parsing + +3. **Phase 10 chambers (mandatory attack modes)**: + - Path traversal (CWE-22) + - Injection (command/env/XML via Docker env) + - Deserialization (JAR/ZIP parsing) + - Race conditions (SQLite, file operations) + - Auth bypass (cookie forging) + +4. **Patch-bypass-checker candidates**: + - No structural-recurrence candidates (new codebase) — but the ZIP extraction code in both `routes/instances.rs` and `routes/backups.rs` should be compared for consistency + +--- + +## References + +- OSV.dev queries: 22 direct deps + 5 transitive checked +- NVD keywordSearch for "minecraft-ui": 0 results +- Git log: 6 commits, no CVE references +- Source analysis: 3,213 lines across 16 Rust files -- cgit v1.2.3