From 2d8a8d1e684dea7d65b679ca60cceb42076bf9e3 Mon Sep 17 00:00:00 2001 From: git-hulk Date: Wed, 13 May 2026 20:36:25 +0800 Subject: [PATCH] Disable loading of Lua bytecode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Loading untrusted Lua bytecode is unsafe — the LuaJIT FAQ explicitly states the bytecode loader does not validate input, and maliciously crafted bytecode can crash the VM or be used for sandbox escapes (type confusion, OOB reads, fake GCobj pointers). Reject any chunk whose lexer setup detects bytecode (BCDUMP_HEAD1, i.e. 0x1B at the start of the stream). All chunk-loading APIs — lua_load, lua_loadx, luaL_loadbuffer(x), luaL_loadfile(x) — funnel through cpparser, so this single check covers loadstring, load, string.dump round-trips, and any host-side luaL_loadbuffer call. Source loading is unaffected. This mirrors the approach Redis took for vanilla Lua in redis/redis@fdf9d455. --- src/lj_load.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lj_load.c b/src/lj_load.c index 0aab488407..13783af4b3 100644 --- a/src/lj_load.c +++ b/src/lj_load.c @@ -34,11 +34,18 @@ static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) UNUSED(dummy); cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ bc = lj_lex_setup(L, ls); - if (ls->mode && !strchr(ls->mode, bc ? 'b' : 't')) { + /* Disable loading of Lua bytecode. Untrusted bytecode is unsafe and can + ** crash the VM or be used for sandbox escapes; see the LuaJIT FAQ. + */ + if (bc) { setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); lj_err_throw(L, LUA_ERRSYNTAX); } - pt = bc ? lj_bcread(ls) : lj_parse(ls); + if (ls->mode && !strchr(ls->mode, 't')) { + setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); + lj_err_throw(L, LUA_ERRSYNTAX); + } + pt = lj_parse(ls); fn = lj_func_newL_empty(L, pt, tabref(L->env)); /* Don't combine above/below into one statement. */ setfuncV(L, L->top++, fn);