diff options
| author | salmonik <salmonik@tuta.io> | 2026-07-29 02:24:41 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-07-29 02:24:41 +0200 |
| commit | c654a6d17eb58adbb15b9c47ab32bcc3a1666307 (patch) | |
| tree | 545544bf7d805254415da787fad1cdc711767833 /piolium/attack-surface/candidates-summary.md | |
| parent | Add per-instance mod management with client-side detection (diff) | |
| download | minecraft-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/attack-surface/candidates-summary.md | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/piolium/attack-surface/candidates-summary.md b/piolium/attack-surface/candidates-summary.md new file mode 100644 index 0000000..69a3d4e --- /dev/null +++ b/piolium/attack-surface/candidates-summary.md | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | # Candidate Scan | ||
| 2 | |||
| 3 | Generated by piolium at 2026-07-28T23:31:42.201Z | ||
| 4 | |||
| 5 | ## Totals | ||
| 6 | |||
| 7 | - Files scanned: 61 | ||
| 8 | - Candidate files: 1 | ||
| 9 | - Candidate matches: 26 | ||
| 10 | - Per-file records: disabled (set PIOLIUM_FILE_RECORDS=1 to enable) | ||
| 11 | |||
| 12 | ## Candidate Classes | ||
| 13 | |||
| 14 | - dynamic-code-execution: 8 match(es), max score 90. Dynamic code execution, expression evaluation, or runtime compilation. | ||
| 15 | - command-execution: 4 match(es), max score 80. Potential command execution or shell invocation with variable input. | ||
| 16 | - path-traversal-file-access: 7 match(es), max score 55. Filesystem access using path joins or user-controllable paths. | ||
| 17 | - hidden-control-channel: 6 match(es), max score 55. Request header or framework/proxy context read that may influence auth, routing, tenant, runtime, debug, or middleware behavior. | ||
| 18 | - unsafe-html-or-template: 1 match(es), max score 55. HTML injection sink or template escape bypass. | ||
| 19 | |||
| 20 | ## Top Files | ||
| 21 | |||
| 22 | - `static/htmx.min.js`: score 1800, 26 match(es) | ||
| 23 | |||
| 24 | ## Highest-Ranked Matches | ||
| 25 | |||
| 26 | - dynamic-code-execution (precise, score 90) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 27 | - dynamic-code-execution (precise, score 90) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 28 | - dynamic-code-execution (precise, score 90) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 29 | - dynamic-code-execution (precise, score 90) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 30 | - dynamic-code-execution (precise, score 90) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 31 | - dynamic-code-execution (precise, score 90) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 32 | - dynamic-code-execution (precise, score 90) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 33 | - command-execution (precise, score 80) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 34 | - command-execution (precise, score 80) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 35 | - command-execution (precise, score 80) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 36 | - command-execution (precise, score 80) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 37 | - dynamic-code-execution (precise, score 80) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 38 | - path-traversal-file-access (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 39 | - path-traversal-file-access (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 40 | - path-traversal-file-access (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 41 | - path-traversal-file-access (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 42 | - path-traversal-file-access (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 43 | - path-traversal-file-access (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 44 | - path-traversal-file-access (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 45 | - unsafe-html-or-template (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 46 | - hidden-control-channel (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 47 | - hidden-control-channel (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 48 | - hidden-control-channel (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 49 | - hidden-control-channel (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 50 | - hidden-control-channel (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 51 | - hidden-control-channel (normal, score 55) at `static/htmx.min.js:1` - var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,add | ||
| 52 | |||
| 53 | ## Custom Matchers | ||
| 54 | |||
| 55 | Project matchers can be added at `piolium/matchers.json`, `piolium/custom-matchers.json`, or `.piolium-matchers.json`. | ||
