Status: Active. Created 2026-06-12 to close the audit gap
(V1_V7_PLAN_SET_AUDIT_2026-06-12.md §6.2, V4): the workshop spec asserts
that "a mod that crashes is caught, auto-disabled, and reported"
(V4/V4_features.md:1728-1731) — a reliability claim — and calls mods
"sandboxed GameFeatures plugins" (:1710-1711) without defining the sandbox.
This document is the security analysis. Its trust-tier decision (§3) and GA
gates (§7) are binding inputs to the workshop launch exit criterion
("Workshop / mod platform live", V4/V4_features.md:2751) and to risk R-08 in
V4/docs/planning/program-risk-register.md.
1. What a GameFeature plugin actually is (the gap in the current claim)#
A UE GameFeature plugin can contain: cooked assets (meshes, textures, audio,
data tables), Blueprint classes (bytecode executed in-process with access to
every BlueprintCallable engine API), GameFeature actions (component/ability
injection into live actors), and — for first-party plugins — native C++
modules. Nothing in the GameFeature subsystem is a security boundary: a
Blueprint runs with the full privileges of the game process. Crash-catching
(V4/V4_features.md:1728-1731) protects against bugs; it does nothing
against malice, and "isolated plugin" describes packaging, not privilege.
Adjacent specced surfaces this model must cover: the mission editor's
"sandboxed" visual script ("scripts cannot call engine internals or arbitrary
code", V4/V4_features.md:1657-1659), the mod manifest/dependency closure
(:1716-1719), immutable versioning (:1732-1734), two-stage content
moderation + takedown cascade (:1723-1727), Steam Workshop + EOS Player
Studio distribution (:1713-1715), and the esports mod whitelist
(:1896-1898).
2. Threat enumeration#
| ID | Threat | Vector | Worst case | Status under current spec |
|---|---|---|---|---|
| T1 | Arbitrary native code in plugins | Mod ships a compiled module; GameFeature loader maps it into the game process | Full RCE on every subscriber's machine; ransomware/credential theft at workshop scale; console TRC catastrophe | Not explicitly forbidden anywhere — must be forbidden (§3) |
| T2 | Blueprint logic mods as de-facto arbitrary code | BP bytecode calls exposed engine APIs: file I/O via save-game/paths nodes, console-command execution, process-level side effects via plugins' loaded classes | Equivalent to T1 in practice (data theft, cheat injection, griefware), while looking like "just a Blueprint" | "Sandboxed" asserted, no mechanism specced — resolved by §3 tiers |
| T3 | UObject / asset deserialization attacks | Malicious .uasset exploits parser/serializer bugs (UE asset loaders have a history of memory-safety CVEs); triggers on load, before any "logic" runs |
RCE from an "asset-only" mod; defeats any logic-tier policy if unmitigated | Unaddressed — mitigated by re-cook pipeline + loader fuzzing (§4) |
| T4 | Cheat distribution via cosmetic mods | Materials with depth-test disabled (wallhack), high-visibility player skins, foliage/smoke-removing meshes, hitbox-revealing particles, tampered data tables | Competitive integrity collapse; EAC (ADR 0008) does not inspect workshop asset semantics | Partially addressed: esports whitelist exists (:1896-1898); ranked needs the same guarantee (§5) |
| T5 | Supply-chain via popular-mod update | Author account compromise → malicious vN+1 offered to the full subscriber base; immutable versions (:1732-1734) protect pins but the update offer path is the attack |
One popular mod = distribution to 10⁵–10⁶ clients in hours | Unaddressed — author 2FA, rescans per version, staged rollout, kill switch (§4, §6) |
| T6 | Dependency-closure attacks | Typosquatted or hijacked dependency in the manifest closure (:1716-1719); client "resolves and downloads the dependency closure" automatically |
Same blast radius as T5, harder to see | Unaddressed — closure pinned by content hash at publish (§4) |
| T7 | Asset-bomb denial of service | Pathological Nanite meshes, 8K texture stacks, runaway Niagara emitters, audio loudness bombs | OOM/hang on constrained platforms (Switch 2, tablets — V4/V4_features.md:300-304); review-bombing-by-crash |
Partially: save quotas exist (:1667-1669); needs budget linting at upload (§4) |
| T8 | Data exfiltration / phishing surfaces | Web/URL-capable widgets or nodes in logic mods; malicious links in workshop descriptions | Credential phishing branded inside the game | Moderation queue helps descriptions; logic-tier API allowlist removes in-game vector (§3) |
| T9 | Moderation-evasion content | Classifier-evading textures/meshes (the two-stage gate at :1723-1725 is image-classifier + reports) |
Brand/legal damage, store delisting | Accepted residual; takedown cascade + §6 revocation bounds exposure time |
| T10 | Platform-holder/cert violation | Any downloaded executable logic on consoles violates TRC/XR content policies | Cert rejection of the base game update carrying the workshop client (risk R-02/R-08) | Resolved structurally by §3: consoles receive Tier-0/Tier-1 only |
3. Trust-tier design — the explicit call#
Decision (binding, planning decision adopted 2026-06-12, to be ratified as an ADR if contested): V4 does NOT distribute arbitrary native code or arbitrary Blueprint GameFeature plugins to client machines. Ever. The workshop's "GameFeatures plugin" packaging is retained, but what a plugin may contain is tiered:
| Tier | Contents | Where it runs | Distribution |
|---|---|---|---|
| Tier 0 — Asset-only | Cooked assets + data tables conforming to published schemas; zero bytecode of any kind | All platforms, incl. consoles via EOS Player Studio | After §4 pipeline (re-cook, scans, signing). "Unrestricted" in availability, never in validation |
| Tier 1 — Interpreted logic | Mission-editor visual scripts (V4/V4_features.md:1657-1659) compiled to a restricted interpreted instruction set executed by a V4-owned interpreter: opcode allowlist, capability-scoped API (spawn/objective/dialogue/trigger verbs only), per-tick instruction budget, no file/net/console access |
All platforms; PvE and custom games only | Same pipeline + interpreter-validation pass |
| Tier 2 — Server-side Blueprint plugins | Full Blueprint GameFeature plugins (new modes, mutators, AI behaviors) | Dedicated servers only — our fleet's custom-game pools and self-hosted unranked servers. Clients receive only replicated state plus the mod's Tier-0 asset payload; the logic plugin never ships to a client process | PC server hosts + first-party fleet; never consoles, never client installs |
| Tier 3 — Native plugins | C++ modules | First-party and contracted-partner code only, through the normal build/signing pipeline, code-reviewed | Not workshop-distributable. No exceptions; a partner native mod is a game patch, not a mod |
Consequences of the call:
- T1 is closed by fiat (Tier 3 not workshop-distributable); T2 is closed by construction (Blueprint logic exists only behind the server boundary, Tier 2); T10 is closed structurally (consoles get no executable content).
- The mission editor's existing sandbox claim becomes true by mechanism: Tier 1 is an interpreter we own, not trust in Blueprint.
- Cost accepted: client-side total-conversion mods (new client logic) are out of scope for V4. That is the price of 9-platform cert and EAC coexistence.
Position relative to V5 and V7#
- V5 (data-only): V5's workshop is "data-only, cannot ship executable
code, and is disabled in ranked PvP and on cert-restricted online surfaces"
(
V5/V5_features.md:2315-2318). V4 Tier 0 matches V5's line; V4 goes further than V5 by adding Tier 1 (interpreted mission logic) and Tier 2 (server-side Blueprint) because V4's creator suite promises per-cell mission logic, which data alone cannot express. - V7 (WASM capability sandbox): V7 lifts the data-only limit with a
Wasmtime Component-Model sandbox — capability-typed WIT host interface,
fuel/epoch CPU budgets,
StoreLimitsmemory caps, six trust tiers, AOT at upload, per-call audit log (V7/V7_ARCHITECTURE.md:338-369), with content-addressed storage + lock files as the supply-chain primitive (:371-384). V4 deliberately stops short of client-side untrusted execution because it has no such runtime: UE Blueprint offers no capability typing, no deterministic fuel metering, and no memory isolation. V4's line: interpretation (Tier 1) + server isolation (Tier 2) substitute for the sandbox V4 doesn't have. Forward-compatibility requirement: the V4 mod manifest carries atrustTierfield whose values map 1:1 onto V7's DataOnly/Scripted/Extended tiers (V7/V7_ARCHITECTURE.md:355-358) so V4 workshop content can migrate when a WASM-class runtime exists; V4 adopts V7's content-addressing model for closure pinning now (§4) since it is runtime-independent.
4. Signing and scanning pipeline (upload → activation)#
- Manifest validation — declared cells, asset list, dependencies, semver,
author identity (
V4/V4_features.md:1716-1719);trustTierdeclared and verified against contents (a Tier-0 mod containing any bytecode is rejected, not downgraded). - Bytecode & class audit — package is statically walked: Tier 0 must contain zero Blueprint bytecode and only allowlisted UObject classes; Tier 1 scripts compile through the first-party toolchain server-side (the uploaded source graph, not author-supplied bytecode, is authoritative); Tier 2 Blueprint passes an API-usage scan (deny-listed nodes: console command exec, file path access outside mod sandbox dir, process/OS nodes).
- Re-cook / re-serialization on trusted infrastructure — every asset is deserialized and re-serialized by our cooker; unknown or malformed structures are dropped, closing the T3 window to the cooker (which we fuzz, §7 G1) rather than every player's client. Clients only ever load first-party-cooked bytes.
- Semantic asset scans — material flags (depth-test disable, unusual translucency sort priorities), mesh/texture/emitter budget linting against per-platform caps (T7), audio loudness normalization, data-table values range-checked against schema bounds (T4 partial).
- Content moderation — the specced classifier + report queue
(
V4/V4_features.md:1723-1727) runs after technical scans. - Content-addressed signing — artifact ID = hash(content + full
dependency closure) (V7 model,
V7/V7_ARCHITECTURE.md:379-384); the workshop service signs {artifact hash, manifest, trustTier, version}. Clients/servers verify signature and the pinned closure hashes before activation — a swapped dependency changes the hash (closes T6). - Per-version re-scan — every update version repeats 1–6 (versions are
immutable,
:1732-1734); update offers to subscribers roll out staged (1% / 24 h → 25% / 24 h → 100%) with automatic halt on crash/report anomaly (T5). - Author account controls — publishing requires 2FA; a publish from a new device/IP triggers step-up verification; author keys never sign anything (only the service signs), so author compromise cannot mint trusted artifacts directly.
5. Competitive-surface guarantees (T4)#
- Ranked and tournament processes load zero workshop content — enforced
by a build-time assertion in the mode-activation path, the same pattern as
the AI-Director PvP exclusion assertion (
V4/V4_features.md:1561-1564), not by playlist configuration. Tournament servers already reject non-whitelisted clients (:1896-1898); ranked inherits the stricter rule: no mods, whitelisted or not. - Custom/unranked lobbies display the active mod set to all players before ready-up; server-side hit validation and EAC remain active regardless.
6. Kill switch and revocation#
- Revocation list (CRL-model): workshop service publishes a signed
revocation feed; clients fetch at session start and on the existing
30-minute hotfix channel (
V4/V4_features.md:1961-1962) for emergency push. Cached CRL is valid offline for 72 h; beyond that, Tier 1/2 content deactivates until the client can revalidate (Tier 0 remains, lower risk — planning assumption adopted 2026-06-12, revisit after Open Beta data). - Revocation classes:
security(T1–T6 findings — immediate hard-disable, subscribers notified, telemetry snapshot of activation counts preserved for incident response),integrity(T4 cheat assets — disable + ranked-history audit hook for affected lobbies),moderation(existing takedown cascade,:1723-1727, including dependent-mod delisting). - Drill requirement: end-to-end revocation (decision → fleet + clients) must complete in ≤15 minutes in staging, exercised quarterly and once before GA (§7 G4).
7. Gates this adds before Workshop GA#
Workshop GA is an exit criterion (V4/V4_features.md:2751). It does not ship
until all of:
- G1 — Cooker hardening: re-cook pipeline operational for all Tier-0 asset classes; ≥500 CPU-hours of coverage-guided fuzzing on the deserialization path with zero outstanding crash/UB findings (planning assumption adopted 2026-06-12 for the fuzz budget); corpus retained and run in CI.
- G2 — Competitive isolation proven: the §5 build-time assertion exists and a red-team attempt to load a mod into a ranked process fails in CI.
- G3 — Signing chain live: content-addressed signing + closure pinning verified on all 9 platforms; author 2FA enforced; staged-rollout machinery tested with a forced halt.
- G4 — Kill-switch drill: ≤15-minute end-to-end revocation demonstrated in staging, all three revocation classes.
- G5 — Platform-holder signoff: written approval of the per-platform UGC scope (Tier 0/1 on consoles, no executable content) from each console holder — due 2026-07-15 per risk R-08's trigger.
- G6 — Service pen test: third-party penetration test of workshop-service upload/entitlement/CDN paths with no open high/critical findings.
- G7 — Interpreter bounty window: Tier-1 interpreter in the security bug-bounty scope for ≥30 days before GA (Open Beta window suffices if the interpreter ships in Open Beta), with sandbox-escape classed as critical.
8. Residual risks (accepted, with eyes open)#
- T3 residual: a cooker-fuzzing gap could still let a crafted asset through — bounded by trusted re-cook (attacker must exploit our cooker output format, not hand-craft bytes) and the 15-minute kill switch.
- T4 residual: semantic scans cannot catch every advantage-granting cosmetic; ranked-zero-mods contains the competitive harm; custom games accept it visibly.
- T9 residual: classifier evasion until report-queue action; bounded by takedown cascade SLA (set: 4 h for confirmed security/integrity, 24 h moderation — planning assumption adopted 2026-06-12).
- Scope cost: no client-side logic total conversions in V4 (revisit when a V7-class WASM runtime is adoptable in UE).
Owners: Security Lead (Trust & Safety) — document of record; Workshop Service Lead — pipeline (§4); Online/Build leads — §5 assertion; Live Ops Director — §6 drills; Platform & Certification Manager — G5.