v6.10.0 — MCP security, six headless demo scenes, and a long tail of silent failures
Acts on fresh audits of all five packages.
⚠️ Security
The in-game MCP server accepted cross-origin requests. Binding to 127.0.0.1 stops network access but not the user's own browser: with Content-Type: text/plain a POST is a "simple" CORS request and skips preflight, so any open web page could call tools/call execute_lua or manage_mods — and DNS rebinding makes the request same-origin, exposing replies including screenshot.
Requests are now screened before routing (IsLocal → Host → Origin → JSON Content-Type) and authenticated with a bearer token, generated per run or pinned via COREAI_MCP_TOKEN. The server remains off by default and is in no shipped scene.
Migration: existing clients must send Authorization: Bearer <token>. The token is printed to the game console with a ready-to-paste command; set COREAI_MCP_TOKEN once for a stable config.
Fixed
- Six published demo scenes ran mods headless —
Instance.newproduced nothing in them.CoreAiHubDemo,LiveMechanicsDemo,LiveMechanicsModsChatDemo,WaveAutoBattlerModsDemo,MiniRpgModsDemoandModdableUnitsDemonow each carry a wiredRbxWorldHost. - Editing a mod in the Hub froze the game.
LLMManager.LoadFromDisk()wiped the LLMUnity model registry in the Editor — a "rescan" that erased the user's registered models, permanently once anything saved afterwards.- A
ChainResetpast the first line no longer verifies an audit log as intact. Truncating the tail and appending a forged restart used to reportOk.
Failures that were silent by construction
- A library timeout surfaced as "cancelled", so it read as if the user pressed Stop and the timeout branch never ran.
- An empty streaming response counted as success while vanishing from history and traces.
MutateAsyncdestroyed a role's memory when the load failed rather than being absent.game_config updatereported success when the store rejected the write.- WebGL:
Task.Delayin the endpoint drain loop never resumed and wedged activation forever; seven unguardedSwitchToThreadPoolcalls hung tool turns; an unclamped transcript entry could crash the player.
Added
GameLogFilter — a real runtime logging API over a runtime copy of the authored ScriptableObject, so filters change in a player without mutating the asset. GameLogFeature.All now actually includes every category (it silently omitted Metrics), the no-asset default no longer ignores categories or mutes everything below Warning, and the static fallback used by ~15 files is finally under the same filter. First tests that prove filtering drops messages, rather than only testing the predicate.
Verification
EditMode: 2539 tests, 0 failed. The demo-scene smoke test passes after the scene fix. Remaining PlayMode failures are a local LM Studio that cannot load its model, plus one pre-existing TargetCube assertion that reproduces identically on a clean HEAD.