Skip to content

fix(controller): escape backslashes and newlines in Lua string encoding - #416

Open
nicknjpconsultingllc wants to merge 1 commit into
JackHopkins:mainfrom
nicknjpconsultingllc:fix/lua-injection-rcon-encoding
Open

nicknjpconsultingllc wants to merge 1 commit into
JackHopkins:mainfrom
nicknjpconsultingllc:fix/lua-injection-rcon-encoding

Conversation

@nicknjpconsultingllc

Copy link
Copy Markdown

slpp.encode (the encoder every RCON tool call goes through in Controller._get_command / _execute_once / execute2) escapes double quotes but not backslashes or newlines. Any string tool argument containing \, \n or \r therefore produces invalid Lua and the call fails:

  • C:\path → invalid escape sequence
  • multi-line text → unfinished string
  • a trailing odd backslash closes the literal early, so the remainder of the argument is parsed as Lua

Fix: _lua_encode_safe pre-escapes \, \n, \r at every string leaf (recursing into dict/list/tuple, since slpp reuses the same string branch for nested values) before lua.encode sees it. slpp's own quote escaping composes correctly on top. No call site can currently rely on a backslash surviving, because none do.

Tests: tests/unit/test_lua_encoding_security.py, 26 cases, server-free under tests/unit/conftest.py. They run the emitted Lua through lupa (already a dependency) in the exact pcall(storage.actions.NAME, ...) shape the controller builds, and check that string content can never escape its literal.

Scope: correctness plus defense in depth, not a security boundary. The agent's program runs in-process with instance in scope and can reach rcon_client directly, so this closes no privilege gap today; it matters if a future frontend passes tool arguments without exposing Python.

Not fixed here: slpp.decode() on the response path has its own escaping limits, and slpp does no escaping of dict keys. Neither is reachable from agent input today.

🤖 Generated with Claude Code

https://claude.ai/code/session_01RNpy6PN7ttQrMRmNABEXK8

slpp.encode escapes double quotes but not backslashes or newlines, so
any string tool argument containing a backslash, \n or \r produces
invalid Lua and the RCON call fails ("invalid escape sequence",
"unfinished string"). A trailing odd backslash also closes the literal
early, so the remainder of the argument is parsed as Lua.

Fix: pre-escape at every string leaf before slpp sees it; slpp's own
quote escaping composes correctly on top. 26 tests run the emitted Lua
through lupa (already a dependency) in the exact
pcall(storage.actions.NAME, ...) shape the controller builds. Tests are
server-free (tests/unit).

Scope: correctness plus defense in depth, not a security boundary. The
agent's program already has `instance` in scope and can reach
rcon_client directly.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNpy6PN7ttQrMRmNABEXK8

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants