# 04 — Mod / Admin Item Classification (BNO legacy GML)

Full classification of the legacy MOD / ADMIN item set so the rebuild can separate **true RCE**
(anti-port — CLAUDE.md Hard Rules 2 & 3) from **reasonably-fenced mod features** that may be worth
re-implementing behind a real admin surface.

Evidence is `path:line` relative to repo root. Trees: `extracted/client-5-8` (client),
`extracted/server-5-4` (server). All evidence is plain-text `.gml` / `.txt` — no binary inspection.

Two distinct admin surfaces exist and must not be conflated:

1. **Client-side mod *items*** — key-data inventory items, ids **900–909**, tokens `<M:...>`.
   A moderator who possesses these items in their inventory gets a context-menu "Trigger" action.
   Registry: `client-5-8/scripts/0347-iv_keyactions.gml`. Network ops use **msgid 20** sub-commands
   handled server-side in `server-5-4/scripts/0359-server_receive.gml:417-469`.
2. **Server-app operator console** — the GM5.3a *server* executable's own keyboard handlers
   (`server-5-4/objects/0000-server/events/KeyPress-*.gml` and `0363-ucontrol`). This is the
   "run clipboard as superuser" admin model named in CLAUDE.md Hard Rule 3. Cross-referenced by the
   operator cheat-sheet `legacy/open-source-release/,ServerCommands.txt`.

---

## Part A — Client mod items (ids 900–909)

Source of truth for behavior: `client-5-8/scripts/0347-iv_keyactions.gml` (the per-item
context-menu action; `global.iv_actions[3,n]` is the GML string `execute_string`'d when the mod
clicks the menu entry). All items 900+ are auto-`deleteable` (`iv_keyactions.gml:359`).

| ID | Token | Name | What it actually does | Class | Evidence |
|----|-------|------|------------------------|-------|----------|
| 900 | `<M:Exc>` | Executor | `execute_string(clipboard_get_text())` — runs clipboard contents as GML on the mod's **own** client. Arbitrary local code exec. | **RCE** | iv_keyactions.gml:132-137 |
| 901 | `<M:Qury>` | Query | `execute_string('meh = ' + keyboard_string + ';')` then prints `meh`. Evaluates an arbitrary GML expression typed into chat. Arbitrary local eval. | **RCE** | iv_keyactions.gml:148-155 |
| 902 | `<M:NetExc>` | Net Executor | Sends msgid 20 / sub 0 + `clipboard_get_text()`. Server runs `execute_string(tempstring)` on the **server**. Arbitrary remote code exec on the authoritative server. | **RCE** | client: iv_keyactions.gml:166-175; server: server_receive.gml:424-430 |
| 903 | `<M:NetQury>` | Net Query | Sends msgid 20 / sub 1 + `keyboard_string`. Server does `execute_string("tempint = " + tempstring + ";")` then ships the result back as **msgid 12**, which the client runs via `execute_string(readstring())`. Arbitrary server-side eval; result path is itself RCE. | **RCE** | client: iv_keyactions.gml:186-196; server: server_receive.gml:431-440; client recv: client_receive.gml:174-176 |
| 904 | `<M:NetTarg>` | Net Target | Sends msgid 20 / sub 2 + `keyboard_string`. Server sets `global.mod_uid = real(tempstring)`. Selects the victim uid for sub 3. Not exec by itself, but exists **only** to aim Net Control. | **RCE** (enabler) | client: iv_keyactions.gml:207-217; server: server_receive.gml:441-445 |
| 905 | `<M:NetCon>` | Net Control(ler) | Sends msgid 20 / sub 3 + `clipboard_get_text()`. Server relays the clipboard string to the targeted uid's socket as **msgid 12** → that victim client runs `execute_string(readstring())`. Arbitrary code exec on **another player's** machine. | **RCE** | client: iv_keyactions.gml:228-237; server: server_receive.gml:446-453; victim recv: client_receive.gml:174-176 |
| 906 | `<M:Loc>` | Location | `iv_additem(3, '0\|1]'+keyboard_string+'\|2]'+global.area+'\|3]'+string(global.zone)+'\|4]'+string(server.x)+'\|5]'+string(server.y))`. Mints a **link-data** item (db 3, area-link) for the mod's current zone/area/x/y, named by the typed string. Purely local; only writes to own inventory; bounded to "make a warp bookmark of where I'm standing." | **FENCED FEATURE** | iv_keyactions.gml:248-255 |
| 907 | `<M:MasMod>` | Mass Moderation | Always-on flag item; its trigger action is the inert "It's always on" stub (just presses Insert). No handler reads a `MasMod` capability anywhere in the extracted trees. Presence-only marker; effect unclear. | **UNCLEAR** | iv_keyactions.gml:262-270 (stub action); no consumer found in client or server grep |
| 908 | `<M:NetPop>` | Net Populate | Sends msgid 20 / sub 4 (no payload). Server builds an "Online: (uid) name [Room N] ..." roster string and ships it back as msgid 12 (`caddline('...')`). **Bounded read-only query** — but delivered over the same msgid-12 `execute_string` channel, so the transport itself is RCE-capable (server controls the string, so safe here, but the channel is the anti-port concern). | **FENCED FEATURE** (data is just a player list); transport channel is RCE | client: iv_keyactions.gml:281-289; server: server_receive.gml:454-468; channel: client_receive.gml:174-176 |
| 909 | `<M:JkrShl>` | Joker Shell | Spawns a `jokershell` ghost (object 0481) at the mod's position; the real Navi freezes as `NaviStandD` and the camera + movement follow the ghost. Ghost walks **anywhere**, ignores fall/edge consequences, moves at speed 7. Re-trigger (Ctrl+I) teleports the real player **to** the ghost (JoinOut→JoinIn). Auto-recall after **90 steps (~3 s @ 30fps)** via `alarm[0]` **unless the clipboard literally equals `"UNLIM"`** (then unlimited). No code-exec, no effect on other players, no persistence. | **FENCED FEATURE** | client: iv_keyactions.gml:300-336; object: objects/0481-jokershell/{Create,Step,Alarm,Other-7}.gml; time-gate: jokershell/Step.gml:19 |

### Notes on the "borderline" cases

- **906 Location** and **909 Joker Shell** are genuinely fenced: bounded capability, local-only or
  server-mediated-but-constrained, no arbitrary code. These match the mission's pre-classification
  (Location = set/record own coords; Joker Shell = time-gated invulnerable ghost). Safe to re-build.
- **908 Net Populate** *data* is a benign online-player roster. But it is delivered via the
  **msgid-12 → `execute_string`** mechanism (`client_receive.gml:175`). In the rebuild a player list
  must be a typed data message, **never** a code string the client evals. The capability is fine;
  the legacy transport is not.
- **907 Mass Moderation** is the one true UNCLEAR. It registers as a key item and has a registry
  entry, but its menu action is the inert always-on stub and **no code in either extracted tree
  reads a MasMod flag**. Likely vestigial / planned-but-unwired, or its enforcement lived in a
  server build not in `server-5-4`. Flagged as a guess — do not assume a behavior.

### The msgid-12 channel (root anti-port concern)

`client-5-8/scripts/0097-client_receive.gml:174-176`:

```
case 12:
  execute_string(readstring());
break;
```

Any server→client msgid-12 packet is **arbitrary code run on the client**. Net Query (903) result,
Net Control (905) payload, and Net Populate (908) roster all ride this channel. This single case is
the load-bearing RCE primitive on the client side and must have **no equivalent** in the rebuild
protocol — server messages are typed data, never executable strings.

---

## Part B — Server-app operator console (the "superuser clipboard" admin)

The GM5.3a *server* executable is itself an interactive operator console. Keyboard handlers on the
`server` object (0000) and the `ucontrol` player-list object (0363) give the operator direct exec.
These are NOT inventory items — they are the operator's local hotkeys. Cross-referenced by
`legacy/open-source-release/,ServerCommands.txt` (the human cheat-sheet).

| Hotkey | Handler | What it does | Class | Evidence |
|--------|---------|--------------|-------|----------|
| Ctrl+E | server KeyPress-69 | `execute_string(clipboard_get_text())` on the server. | **RCE** | objects/0000-server/events/KeyPress-69.gml:2-5 |
| Ctrl+Q | server KeyPress-81 | `execute_string("dynamicaddline('"+keyboard_string+" = '+string("+keyboard_string+"));")` — eval arbitrary expression from input field. | **RCE** | objects/0000-server/events/KeyPress-81.gml:2-6 |
| Ctrl+O | server KeyPress-79 | Opens `scontrolmenu()` snippet picker, then `get_string` for code and sends it as **msgid 12** to the selected player's `operations` object → victim client runs it. Remote RCE on a chosen player. | **RCE** | objects/0000-server/events/KeyPress-79.gml; scripts/0364-scontrolmenu.gml |
| Ctrl+O (alt, on player list) | ucontrol KeyPress-79 | `writebyte(12); writestring(clipboard_get_text())` → highlighted player. Sends clipboard code to the selected player to run. | **RCE** | objects/0363-ucontrol/events/KeyPress-79.gml:5-9 |
| Ctrl+M | server KeyPress-77 | Open a message board by ID to view (`get_string` → `mb_cboard`). Read-only board viewer. | **FENCED FEATURE** | objects/0000-server/events/KeyPress-77.gml |
| Ctrl+S | server KeyPress-83 | `view_object[0] = <target player's instance>` — spectate the targeted player's camera. | **FENCED FEATURE** | objects/0000-server/events/KeyPress-83.gml |
| Ctrl+U | server KeyPress-85 | `view_object[0] = server` — return camera to the server's own view (un-spectate). | **FENCED FEATURE** | objects/0000-server/events/KeyPress-85.gml |

`scontrolmenu()` (the Ctrl+O snippet menu) returns canned code strings the operator sends to a
player: "Send Server Message", "Change Running Speed" (`server.curspeed = 3`), "Change Input Text"
(`keyboard_string = ""`), "Move Player" (`server.x += 0; server.y += 0` — template), and **"Force Log
Out"** (`show_message("ERROR: All your game are belong to us."); game_end();`). Every option is GML
shipped to the victim client and `execute_string`'d there — so the menu is a convenience UI on top of
the same RCE channel. (scripts/0364-scontrolmenu.gml:1-25)

### Operator cheat-sheet cross-reference (`,ServerCommands.txt`)

`legacy/open-source-release/,ServerCommands.txt` documents the operator hotkeys in prose and matches
the handlers above: Ctrl+E = execute clipboard; Ctrl+Q = show variable; **Ctrl+9 = context menu of
code snippets to use on players**; Ctrl+??? = send clipboard code to highlighted player; Ctrl+M =
view message boards. ("Ctrl+9" in the sheet corresponds to the `scontrolmenu()` / `show_menu` snippet
picker invoked from the Ctrl+O send flow.)

### `Ctrl+O Codes.txt` (operator's saved snippets)

`legacy/servers/{local-current,enlyzeam-current,enlyzeam-archive}/Ctrl+O Codes.txt` are the
operators' personal libraries of `global.awesomefunction` GML strings (bound to a Ctrl+O macro) —
e.g. store/restore own coords (Ctrl+A / Ctrl+Alt+A), or trigger a directional hexport. These are
hand-authored arbitrary GML; they demonstrate the model's "admin = write code, bind to a key, run it"
nature. Anti-port by definition (arbitrary GML), though the *intents* (teleport-to-saved-coord,
self-hexport) are themselves fenced features worth offering as first-class admin buttons.

---

## Recommended for ReBNO admin surface (the fenced ones)

Re-implement these as **typed, server-validated admin actions** behind the authenticated Phase-7 web
admin UI (CLAUDE.md Hard Rule 3) — never as code strings:

1. **Location / coord bookmark (906)** — let an admin record/jump to named coordinates. Pure data
   (zone/area/x/y). Also covers the `Ctrl+A`-style "store location / set to stored" macro from
   `Ctrl+O Codes.txt`.
2. **Joker Shell (909)** — a bounded, time-gated, consequence-free "ghost walk + teleport-to-ghost"
   testing/assist tool. Keep the time-gate (drop the `"UNLIM"` clipboard backdoor; make the duration
   a server-set admin config). Server-authoritative invuln window; no client trust.
3. **Online-player roster (908)** — admin "who's online + which room" list. Trivial typed query;
   absolutely **must not** reuse a code-eval channel.
4. **Spectate player / return-to-self (Ctrl+S / Ctrl+U)** — camera-follow a chosen player; read-only.
5. **View message board by ID (Ctrl+M)** — read-only board viewer for moderation.
6. **Self-hexport macro** (from `Ctrl+O Codes.txt`) — a fixed, parameterless "hexport in the
   direction I'm facing / exit" action; bounded movement effect, fine as a button.

## Anti-port (RCE) — must NOT be reimplemented

These are arbitrary-code-execution / unbounded admin and are explicitly dropped per CLAUDE.md Hard
Rules 2 & 3:

- **900 Executor** — local clipboard `execute_string`.
- **901 Query** — local arbitrary expression eval.
- **902 Net Executor** — arbitrary code on the authoritative server.
- **903 Net Query** — arbitrary server-side eval, result returned over the code-eval channel.
- **904 Net Target** — victim selector that exists only to aim Net Control.
- **905 Net Controller** — arbitrary code on another player's client.
- **Server console Ctrl+E / Ctrl+Q** — operator-local `execute_string`.
- **Server console Ctrl+O (both variants)** — ship arbitrary clipboard GML to a player's `operations`
  object to run; `scontrolmenu()` "Force Log Out" etc. ride this same channel.
- **`global.awesomefunction` / `Ctrl+O Codes.txt` macros** — arbitrary GML bound to operator keys.
- **The msgid-12 `execute_string(readstring())` client receive case** — the underlying RCE primitive
  enabling 903/905/908-transport and all Ctrl+O sends. No typed-message equivalent may ever eval a
  server-supplied string on the client.

---

## Open questions / flagged guesses

1. **907 Mass Moderation** — UNCLEAR. Registered key item, but its action is the inert always-on stub
   and **no consumer of a MasMod flag exists** in `client-5-8` or `server-5-4`. Either vestigial, or
   enforced in a server revision not in this extract. Behavior is a guess; do not assume.
2. The `,ServerCommands.txt` "Ctrl+9 = context menu" maps to `scontrolmenu()` (`show_menu`), reached
   via the Ctrl+O send flow in this extract; the literal key binding ("9" vs "O") may differ between
   the cheat-sheet's documented build and `server-5-4`. Functionally identical (snippet picker →
   msgid-12 send).
3. Registry/display-name strings for 900–909 (the `global.keydata[id,...]` rows) live in
   `client-5-8/objects/0034-title/events/Other-2.gml` (per doc 02); not re-verified here — behavior
   was read directly from the handler, which is authoritative for what each item *does*.

[doc->REQ-SRV-04]
