Skip to content

Conversation

@anonhostpi
Copy link

@anonhostpi anonhostpi commented Oct 12, 2025

  • adds _VERSION check fix for Luau (the targeted sandbox, which is 5.1 compliant)
  • adds stubs for:
    • io.open
    • io.write

@anonhostpi anonhostpi changed the title Support Luau in template environment Support Luau Oct 12, 2025
Adds `io.open` and `io.write` stubs when they are absent
@anonhostpi anonhostpi changed the title Support Luau Support IO sandboxed environments Oct 12, 2025
@anonhostpi anonhostpi marked this pull request as ready for review October 12, 2025 07:57
@bungle
Copy link
Owner

bungle commented Nov 10, 2025

@anonhostpi thanks, interesting.

@anonhostpi
Copy link
Author

Happy to contribute. Will try to reply quickly, if you need any work done

@bungle
Copy link
Owner

bungle commented Nov 11, 2025

@anonhostpi, I am wondering what else in this library could be non-sandbox safe. Things like setfenv, load, and loadstring could also be problematic.

@anonhostpi
Copy link
Author

It depends on the sandbox.

The majority of sandboxes are just IO isolated (Lua on WASM, Luau, embedded Lua, etc).

Let me take another gander at it.

@anonhostpi
Copy link
Author

anonhostpi commented Nov 11, 2025

So if we want to address all sandboxes (not just IO-sandboxes, but maybe security sandboxes too), we'd need to either annotate minimum requirements and/or make changes to the following

  • load+setfenv (or just loadstring) is required for the loader to work (jit is also used here):
    • POSSIBLE IMPROVEMENT: instead of doing a version check (for 5.1), check which function set is available instead
      • this would eliminate jit usage entirely
    • this is the only time load, setfenv, loadstring, and jit are used.
    • UPDATE: change implemented, needs to be documented on README
    • UPDATE 2: DONE

local loader
if jit or _VERSION ~= "Lua 5.1" then
loader = function(template)
return function(view)
return assert(load(view, nil, nil, setmetatable({ template = template }, VIEW_ENV)))
end
end
else
loader = function(template)
return function(view)
local func = assert(loadstring(view))
setfenv(func, setmetatable({ template = template }, VIEW_ENV))
return func
end
end
end

  • _G/_ENV:
    • this is already partially stubbed:
    • POSSIBLE IMPROVEMENTS (x2):
      • use _G and _ENV presence checks instead of a version check
      • add a third optimized option that doesn't include _G/_ENV indexing when they are absent
    • UPDATE: DONE

local VIEW_ENV
if _VERSION == "Lua 5.1" then
VIEW_ENV = { __index = function(t, k)
return t.context[k] or t.template[k] or _G[k]
end }
else
VIEW_ENV = { __index = function(t, k)
return t.context[k] or t.template[k] or _ENV[k]
end }
end

  • require:

    • this is only used once, and it is already stubbed out.
  • ngx:

    • referenced several times, but already stubbed out for non-resty/ngx environments.
  • string.dump:

    • not stubbed out, but already calls open, which would throw in IO sandboxes.
    • POSSIBLE IMPROVEMENT check that dump and open are defined before declaring
    • UPDATE: change implemented (disabled precompile in applicable sandboxed environments), needs to be documented on README
    • UPDATE 2: change documented
      • need to update how I did IO protection, as its currently wrong
    • UPDATE 3: DONE

function template.precompile(view, path, strip, plain)
local chunk = dump(template.compile(view, nil, plain), strip ~= false)
if path then
local file = open(path, "wb")
file:write(chunk)
file:close()
end
return chunk
end

@anonhostpi
Copy link
Author

In addition to adding minimum requirements and sandboxing notes to the README (load vs loadstring+setfenv), I also added more technical verbage such as JIT-compiling, AOT-compiling, bytecode (for template.precompile), and transpiling (for template.parse)

@anonhostpi
Copy link
Author

anonhostpi commented Nov 11, 2025

Files changed tab looks a bit boggling now.

I double-checked, but in case you want to look yourself, there should only be 3 pieces of removed code:

  • jit - no longer needed as version checks are replaced with presence checks
  • _VERSION - same
  • path argument on transpile.precompile
    • still present on the normal 3 template.precompile... functions, but removed on the 3 IO-sandboxed variations

Only one type of sandbox can't be supported (for obvious reasons) and that is one that doesn't have JIT support (load/loadstring+setfenv). All others should be supportable by the proposed change (IO, string.dump, etc)

@anonhostpi anonhostpi changed the title Support IO sandboxed environments Support sandboxed environments Nov 14, 2025
@anonhostpi
Copy link
Author

I suppose looking back at the comment history of this thread, it might have made sense to add support for the other sandboxes as a secondary PR 😅. Oh well, here they are altogether.

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