Blender add-on: server hardening (opt-in session token, intent purge, bind guard) #1

Merged
libby merged 2 commits from libby/blender-server-hardening into main 2026-11-07 12:52:41 +00:00
Member

Hardens the Blender add-on's CultMesh server (surfaces/blender/brokkr_bridge).

What it does

Always on

  • Queued command intents are purged on server start and stop: every brokkr.blender.command_intent.v0 record in the node (.brokkr/blender-editor.ccmp) and every blender/commands/*.json under the debug root.
  • After Start the panel shows the bind address and port and the cultlib_py_src path cultmesh_py was loaded from.
  • A non-loopback Serve Host (0.0.0.0, LAN address, any hostname but localhost) is refused unless Allow Non-Loopback Bind is ticked by hand in the add-on preferences. While such a server runs the panel shows a warning.

Opt-in, default OFF: Require Session Token

  • Off: no token is generated, nothing is checked, nothing is shown.
  • On: Start generates a secrets.token_urlsafe(32) token, shows it in the panel, and the server rejects every document put and delete without it in a top-level sessionToken envelope field. Checked on every write, not only at connect. Reads stay open. Stop/quit/disable revokes it. Held in memory only, never saved.
  • Refusal is a codeless cultnet.error.v0 (that code list is closed; no new code added).

Why the token is opt-in

Per Meta (operator, owner of the machine): per-write access control on internal infrastructure is not worth the friction by default. The cheap controls that remove real exposure (stale-intent purge, loopback-only unless deliberately widened, visible bind/path) stay mandatory; the token is there to switch on when wanted.

Design notes

  • server_guard.py is stdlib-only (no bpy). The token check is a subclass of cultmesh_py.CultMeshLocalServer overriding _handle_connection_message, the one method every TCP and RUDP message passes through. That is a private method of CultLib; if it is renamed, test_token_on_refuses_unauthenticated_put_on_the_real_server fails.
  • Dropped from the earlier gate-review list, per Meta's amendment: re-confirmation when cultlib_py_src changes between starts. The path is displayed at every start instead.

Tests

CULTLIB_PACKAGES=<CultLib>/packages python -m unittest discover -s surfaces/blender/tests -v : 17 tests, all pass here with CultLib main and msgpack (token randomness/exact match/revoke, per-put check, reads open, bind rules, purge of node + debug files only, stop revokes+purges, real server: default has no token and purges stale files, token on refuses a bare put, non-loopback refused). Without CULTLIB_PACKAGES the 3 real-server tests skip.

Not tested

Blender itself (not installed or run): the panel drawing, the preference properties, the Start operator's error reporting. RUDP path of the real server is covered only through the shared method, not over a socket.

Not merged.

🤖 Generated with Claude Code

Hardens the Blender add-on's CultMesh server (`surfaces/blender/brokkr_bridge`). ## What it does **Always on** - Queued command intents are purged on server **start and stop**: every `brokkr.blender.command_intent.v0` record in the node (`.brokkr/blender-editor.ccmp`) and every `blender/commands/*.json` under the debug root. - After Start the panel shows the bind address and port and the `cultlib_py_src` path `cultmesh_py` was loaded from. - A non-loopback `Serve Host` (`0.0.0.0`, LAN address, any hostname but `localhost`) is refused unless **Allow Non-Loopback Bind** is ticked by hand in the add-on preferences. While such a server runs the panel shows a warning. **Opt-in, default OFF: Require Session Token** - Off: no token is generated, nothing is checked, nothing is shown. - On: Start generates a `secrets.token_urlsafe(32)` token, shows it in the panel, and the server rejects every document put and delete without it in a top-level `sessionToken` envelope field. Checked on **every** write, not only at connect. Reads stay open. Stop/quit/disable revokes it. Held in memory only, never saved. - Refusal is a codeless `cultnet.error.v0` (that code list is closed; no new code added). ## Why the token is opt-in Per Meta (operator, owner of the machine): per-write access control on internal infrastructure is not worth the friction by default. The cheap controls that remove real exposure (stale-intent purge, loopback-only unless deliberately widened, visible bind/path) stay mandatory; the token is there to switch on when wanted. ## Design notes - `server_guard.py` is stdlib-only (no bpy). The token check is a subclass of `cultmesh_py.CultMeshLocalServer` overriding `_handle_connection_message`, the one method every TCP and RUDP message passes through. That is a private method of CultLib; if it is renamed, `test_token_on_refuses_unauthenticated_put_on_the_real_server` fails. - **Dropped from the earlier gate-review list, per Meta's amendment:** re-confirmation when `cultlib_py_src` changes between starts. The path is displayed at every start instead. ## Tests `CULTLIB_PACKAGES=<CultLib>/packages python -m unittest discover -s surfaces/blender/tests -v` : 17 tests, all pass here with CultLib `main` and msgpack (token randomness/exact match/revoke, per-put check, reads open, bind rules, purge of node + debug files only, stop revokes+purges, real server: default has no token and purges stale files, token on refuses a bare put, non-loopback refused). Without `CULTLIB_PACKAGES` the 3 real-server tests skip. ## Not tested Blender itself (not installed or run): the panel drawing, the preference properties, the Start operator's error reporting. RUDP path of the real server is covered only through the shared method, not over a socket. Not merged. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Optional per-session token (preference, default off): random secrets token at
  Start Server, shown in the panel, required in the sessionToken envelope field on
  every document put and delete, revoked on Stop, never persisted.
- Always on: queued command intents (node records and debug command JSONs) are
  purged on server start and stop; the panel shows the bind address and the
  cultlib_py_src path; a non-loopback Serve Host is refused unless the
  Allow Non-Loopback Bind preference is ticked, with a panel warning while running.
- Tests without Blender, plus real cultmesh_py server tests when CULTLIB_PACKAGES is set.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- The guarded server removes sessionToken from put/delete messages before the store,
  which copies envelope fields into the shard log it serves.
- Copy Session Token operator.
- Panel shows cultmesh_py's loaded __file__, not the preference path.
- Unticking Allow Non-Loopback (and any refused start) stops a running non-loopback server.
- stop_server revokes, purges and clears state even if the socket stop raises.
- Tests: shard-log token leak on the real server, node half of the start purge, purge
  persisted across reopening the .ccmp, allow=True through start_server, finally-path.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
libby merged commit 679020d858 into main 2026-11-07 12:52:41 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/Brokkr!1
No description provided.