csrf support

This commit is contained in:
Sky Johnson 2025-05-01 16:25:07 -05:00
parent efcad468ad
commit a6420423a9

View File

@ -10,11 +10,16 @@ __http_response = {}
__module_paths = {} __module_paths = {}
__module_bytecode = {} __module_bytecode = {}
__ready_modules = {} __ready_modules = {}
__EXIT_SENTINEL = {} -- Unique object for exit identification
-- ====================================================================== -- ======================================================================
-- CORE SANDBOX FUNCTIONALITY -- CORE SANDBOX FUNCTIONALITY
-- ====================================================================== -- ======================================================================
function exit()
error(__EXIT_SENTINEL)
end
-- Create environment inheriting from _G -- Create environment inheriting from _G
function __create_env(ctx) function __create_env(ctx)
local env = setmetatable({}, {__index = _G}) local env = setmetatable({}, {__index = _G})
@ -35,10 +40,15 @@ function __execute_script(fn, ctx)
__http_response = nil __http_response = nil
local env = __create_env(ctx) local env = __create_env(ctx)
env.exit = exit
setfenv(fn, env) setfenv(fn, env)
local ok, result = pcall(fn) local ok, result = pcall(fn)
if not ok then if not ok then
if result == __EXIT_SENTINEL then
return
end
error(result, 0) error(result, 0)
end end
@ -314,6 +324,58 @@ local session = {
end end
} }
-- ======================================================================
-- CSRF MODULE
-- ======================================================================
local csrf = {
generate = function()
local token = util.generate_token(32)
session.set("_csrf_token", token)
return token
end,
field = function()
local token = session.get("_csrf_token")
if not token then
token = csrf.generate()
end
return string.format('<input type="hidden" name="_csrf_token" value="%s" />', token)
end,
validate = function()
local env = getfenv(2)
local token = false
if env.ctx and env.ctx.session and env.ctx.session.data then
token = env.ctx.session.data["_csrf_token"]
end
if not token then
http.set_status(403)
__http_response.body = "CSRF validation failed"
exit()
end
local request_token = nil
if env.ctx and env.ctx.form then
request_token = env.ctx.form._csrf_token
end
if not request_token and env.ctx and env.ctx._request_headers then
request_token = env.ctx._request_headers["x-csrf-token"] or
env.ctx._request_headers["csrf-token"]
end
if not request_token or request_token ~= token then
http.set_status(403)
__http_response.body = "CSRF validation failed"
exit()
end
return true
end
}
-- ====================================================================== -- ======================================================================
-- UTIL MODULE -- UTIL MODULE
-- ====================================================================== -- ======================================================================
@ -404,5 +466,6 @@ local util = {
_G.http = http _G.http = http
_G.session = session _G.session = session
_G.csrf = csrf
_G.cookie = cookie _G.cookie = cookie
_G.util = util _G.util = util