v2.39.4 — audit patch: security hardening + data-safety guards - #22
Merged
Conversation
…xtByCategory fed the raw URL segment into Path.Combine, so ..%2f traversal (or an absolute path, which replaces the folder outright) escaped Assets/MCP/Context. Category names are now allowlisted to a plain filename optionally under Custom/. Live-verified: 6 traversal/absolute/NUL payloads blocked, plain + Custom/ + bare-name lookups still resolve [FIX] Bridge, browser-reachable dispatch : the Origin check only ran when an Origin was present, but a no-cors subresource load (img/iframe) sends none - a visited page could reach the bridge. Refuse requests carrying browser Sec-Fetch-Site/Mode metadata (page script cannot forge them) and require POST on every non-read-only route [FIX] Bridge, unbounded inbound body : ReadToEnd had no limit, so one local request could OOM the editor. Cap at 32MB with a 413, including chunked bodies with no declared length [FIX] Asset, delete was silent + permanent + unconfined : route through MCPAssetSafety, refuse a FOLDER unless recursive:true (disclosing the contained asset count), default to the OS trash (permanent:true keeps the hard delete). Asset deletion registers no undo, so undo/last could never recover it [FIX] Scene, new discarded unsaved work with no warning : scene/new replaced the current scene unguarded while scene/open 20 lines above had a check. Both now refuse when ANY loaded scene is dirty unless saveFirst/discardUnsavedChanges [FIX] Scene, modal dialog raised from the request pump : SaveCurrentModifiedScenesIfUserWantsTo blocks the editor on a human click and blocks forever unattended. Decide from the arguments instead [FIX] Asset, create-prefab missing the overwrite guard create-material already had : overwriting kept the .meta GUID so scene references silently re-bound [FIX] Bridge, unregistered from the instance registry on every domain reload : that entry is what the server's compile-resilience relies on, so a routine recompile looked like the project had gone away. Stop(false) across reloads [FIX] ProBuilder versionDefine 4.0.0 -> 5.1.0 : MakeUnique() only exists from 5.1.0, so PB 4.x-5.0.x failed to compile the whole assembly - a dead plugin, not a degraded feature [CLEAN] License : declared MIT while the shipped LICENSE is the AnkleBreaker Open License v1.0 (attribution required, resale prohibited)
…emove : SaveOpenScenes() on a never-saved scene raises the native Save Scene panel, so the escape hatch reintroduced the pump-blocking dialog. Refuse saveFirst when any dirty scene has no asset path, naming those scenes [FIX] Scene, save opened the native Save panel on a never-saved scene : scene/save now takes an optional path (also acting as Save-As, confined via MCPAssetSafety) and refuses with requiresPath instead of blocking the pump on a human when neither the scene nor the caller supplies one Both found by the blind-spot audit reviewing the guard added earlier in this same wave.
…ter the 2.39.4 entry was written (saveFirst re-raising the Save Scene panel, and scene/save gaining an optional path)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Patch release from a 43-run audit (33 dimensions + 10 blind-spot dimensions, 168 agents, every CRITICAL/HIGH adversarially verified). Companion server: 2.35.5.
The audit's own verdict on the codebase: fundamentals are strong, but "a correct pattern gets built once and then not propagated, and safety mechanisms fail OPEN instead of closed." Almost every fix below is "the correct code already existed elsewhere in the same file."
🔒 Security
.mdfile read over an unauthenticated GET —MCPContextManager.GetContextByCategoryfed the raw URL segment intoPath.Combine, so..%2ftraversal (or an absolute path, which replaces the folder outright) escaped the context folder. Category names are now allowlisted. Live-verified: six traversal/absolute/NUL payloads blocked, while plain,Custom/-prefixed and bare-name lookups still resolve.<img>,<iframe>) sends none, so a page a developer merely visited could reach the bridge. Requests carrying browserSec-Fetch-*metadata are refused (page script cannot forge those headers), and every non-read-only route now requires POST.ReadToEnd; one local request could OOM the editor.🛡️ Data safety
asset/deletewas silent, permanent and unconfined. Now path-confined, refuses a FOLDER unlessrecursive:true(disclosing the contained asset count), and defaults to the OS trash — asset deletion registers no undo, sounity_undo_lastcould never recover it.scene/newreplaced the current scene with no dirty check whilescene/opentwenty lines above had one. Both now refuse when ANY loaded scene is dirty unlesssaveFirst/discardUnsavedChanges.saveFirstpath, caught by the follow-up audit reviewing code added minutes earlier in this same wave.asset/create-prefabgot the overwrite guardcreate-materialalready had (overwriting kept the.metaGUID, silently re-binding every scene reference).⚙️ Reliability
MakeUnique()only exists from 5.1.0, so ProBuilder 4.x–5.0.x failed to compile the entire assembly: a dead plugin, not a degraded feature.MITwhile shipping the AnkleBreaker Open License v1.0.Gates
0 Unity compile errors (verified against a live 6000.3.9f1 editor), companion server 60/60 tests, route registry 337 in sync, guards verified end-to-end through the real MCP.
Full detail:
CHANGELOG.md.