senn-techsenn-tech
Security
Security2026-10-14· By Franz Senn

Reading a game-modding plugin before installing it: session hooks, a cloud key and 242 field notes

Since late September the feeds are full of the same trick: Skate physics inside Call of Duty Modern Warfare 2, Minecraft inside Elden Ring, Spider-Man inside Batman Arkham Knight. VGC lists the examples, linked below. Behind it is rarely magic and usually a toolbox called universal-modder. It is a plugin for Claude Code, Codex, Cursor, VS Code and the Gemini CLI, plus a command line tool named um and a knowledge base of field notes. I wanted to know what a person actually invites into the house, so I read the clone before installing anything. State of 14 Oct 2026, branch main, commit 201569a, 644 tracked files.

Four places turned out to matter, and each of them is worth opening in any agent plugin before you switch it on: a hook, a cloud channel, the depth of a scan, and a list of refusals.

What the manifest fires when a session starts

The first finding sits in .claude/settings.json. The plugin registers a script there for the SessionStart event with the matcher startup|resume|clear|compact. On start, on resume and after every context compaction, a shell file from the plugin runs: hooks/add-to-path.sh.

The file itself is tidy. It checks that the root path is set, converts a Windows path under Git Bash, exits 0 when bin/um is not executable, and writes its PATH line only once because it greps for its own marker first.

The content is the lesser point here. A plugin carries its own hook, and that hook runs in every project folder where the plugin is switched on. A README says nothing about it. We measured this plugin format and its permissions last week, including the difference between a hook, a skill and an MCP server: Claude mods: what the new plugin format actually grants in Claude Code.

What leaves the machine on the first generated image

The second finding is absent from the discussion about these clips so far. Installing the plugin pre-configures a cloud channel, in five files at once: .mcp.json, .codex/config.toml, .cursor/mcp.json, .vscode/mcp.json and gemini-extension.json. All five carry the same address https://mcp.fal.ai/mcp with the header Authorization: Bearer ${FAL_KEY}.

The command line does the same over REST. The module docstring in um/fal.py states it: "Local files passed as inputs are uploaded to fal storage first." The implementation is _upload_cdn(): first a short-lived token from https://rest.fal.ai/v1/storage/auth/token, then one POST of the raw file bytes to https://v3.fal.media/files/upload, sent with User-Agent: universal-modder. The reply is an access_url. If the upload fails, files under 8 MiB travel along as base64 data URIs inside the request. Every call appends endpoint, inputs, request id and seed to fal_manifest.jsonl, so any asset can be rebuilt later.

That is documented properly and traceable, and it is still cloud work. The local fallback lane is um comfy, which drives a ComfyUI on your own machine, without audio, without 3D, without video. The clip we watched draws its Creeper with code the model wrote itself and mentions neither fal nor a key. For that particular test the local lane is what ran, and the first audio cue or 3D part leaves you standing there without a configured lane.

What the scan learns about your machine

um scan --list collects a lot about the machine it runs on. The implementation reads the Windows registry for the Steam path, parses libraryfolders.vdf and the app manifests, adds Epic and Xbox installs, and walks the user folders including Documents, which is often redirected to OneDrive. Per game it identifies the engine, the scripting runtime, the anti-cheat present, installed mod loaders and the save locations.

One finding in the plugin's favour: um/scan.py contains no network calls, so the recon stays on the machine. The same file does enumerate every save game, and an agent later asked to write a mod file knows the paths to exactly those saves. The backup warning in the clip is therefore fair, and um backup exists too, with a timestamp and a manifest inside the zip.

What the plugin forbids itself

The fourth layer is a ban list, and it lives in references/safety.md. Allowed: single-player or servers you run yourself. Refused: aimbots, ESP and wallhacks, speed and teleport hacks, recoil scripts and packet manipulation, in the original wording "whatever the framing". Kernel or user-mode anti-cheat is defined there as a stop sign for code injection, and the file names EasyAntiCheat, BattlEye, Vanguard, EA Javelin, Ricochet, ACE, nProtect, XIGNCODE and mhyprot. Disabling or bypassing anti-cheat, spoofing hardware IDs and tampering with DRM or ownership checks are on the never list. Analysing your own legally installed copy is fine, and a dump stays outside any repository.

CONTRIBUTING.md draws the same line for the knowledge base: no game files, no extracted assets, no ROMs, no decompiled code dumps, no secrets. um publish check does not stop at appeals, it checks with a list of regular expressions: the fal key format, a FAL_KEY assignment, sk-ant-, sk-proj- and sk-svcacct-, GitHub tokens up to github_pat_, AWS access key ids, private key blocks, .env files. On top of that it tests whether a file is byte-identical to a file in the game's installation. Running the same command over your own mod folder hands you a free secret scan.

The knowledge base is the reason the repository has 644 files at all: 242 field notes about specific games, each with the version it was written against, the route taken, how it was verified and the traps that cost hours. Agents write them, pull requests review them. um kb pr without --yes is a dry run, and it first runs the secret and decompilation checks; the text in the code says "Ask your human before".

Is the popularity real

We ran this question once before, on 11 Oct, against a different reverse-engineering tool and found a manufactured curve: REA: 83,000 GitHub stars in 44 hours, measured. The same battery shows the opposite here.

The repository was created on 30 Sep 2026 at 05:00:35 UTC, has 223 commits and an MIT licence. At 18:38 UTC on 14 Oct I count 7,608 stars, 814 forks, 48 watchers and 97 contributors. Four pages of the fork list give 2.0, 2.1, 2.9 and 2.8 forks per hour, a flat adoption curve with no plateau through the night hours. The companion metrics agree: 97 contributors are 1.3 percent of the stars, where REA had 0.10 percent. Of the last 100 public events, 38 are pull requests, 34 are comments and 14 are watch events. At REA, 77 watch events fitted into under three minutes.

Public events of the repository, last 100Pull requests38Comments34Watch (star)14Pushes9Forks3Other2040
Own measurement on 14 Oct 2026, around 18:40 UTC, against GitHub's public events API. Event types of the last 100 entries. (Quelle: Own measurement via the GitHub API)

For a repository that sat in every feed five days after it appeared, I had expected an overdriven curve. A mix of pull requests and comments is the pattern of people working on the tool, and the same test on a repository with a comparable counter failed three days ago.

Four files before you install

FileWhat it grantsWhat I look at
.claude/settings.json, hooks/hooks.jsoncommand execution at session start, on every resume and after compactionthe matcher and the script's body. The file name tells you nothing
.mcp.json and its four client siblingsa permanent channel outward, with a key from the environmenttarget host, headers, tool list. One entry in five files is easy to miss
safety.md, CONTRIBUTING.mdwhat the agent is supposed to refusewhether the rule is enforced in code or only written down
um publish check, um kb checka built-in secret and asset gateread the regex list, then use it yourself

The procedure is the same for every plugin. Manifest and hooks first, then the MCP configuration, then the rule files, and finally a look at the check's code lines. Four files, ten minutes. For a tool that enumerates your installed games, lists your save games and pushes images into a cloud, that is the whole job before you switch anything on.

Further reading

Questions?
Do I need fal.ai to build a mod with this plugin?+

No. Images have a fallback lane in `um comfy`, which runs a ComfyUI on your own machine. That lane has no audio, no 3D and no video. The five client files the plugin ships still point at fal.ai's hosted MCP server first, and that one requires `FAL_KEY`.

Is the SessionStart hook dangerous?+

The script itself is harmless: it puts the plugin's bin directory on the PATH and exits cleanly when nothing executable lives there. The point is the mechanism. A plugin carries its own hook, and that hook runs without asking, in every project folder where the plugin is switched on.

Is the repository's popularity real?+

By our measurement, yes. 7,608 stars with 814 forks, 97 contributors and a fork rate of 2 to 3 per hour held flat over fourteen days. Of the last 100 public events, 38 are pull requests and 34 are comments. Only 14 are watch events.