'site:' scheme can, by default, access files outside of the serve directory, and within private directory. I need to limit that, since I essentially take path from the user and embed the file into the response page, and I don't want users accessing files outside the site or within private directory. What somewhat complicates things further is my use of symbolic links where I link file, say, from '/mnt/videos/outside_file' into the website to '/videos/outside_file'. I devised a function for that purpose:
require "java"
local Luan = require "luan:Luan.luan"
local error = Luan.error
local String = require "luan:String.luan"
local starts_with = String.starts_with or error()
local Io = require "luan:Io.luan"
local uri = Io.uri or error()
local Http = require "luan:http/Http.luan"
local site_path = uri("site:/.").java.file.toPath().toRealPath().toString()
local private_path = site_path.."/private/"
local function safe_site_file(path, loading)
local u = uri( Http.dir..path, loading )
u.uri_string = "site:"..path
local file_path = u.java.file.toPath().toAbsolutePath().normalize().toString()
starts_with(file_path, site_path) or error("trying to access a file outside of the site: "..path)
starts_with(file_path, private_path) and error("trying to access the private directory: "..path)
return u
end
That works perfectly locally, but Luanhost gives the following error:
Internel Server Error
Security violation - only luan:* modules can load Java
site:/init.luan line 1
I suggest either:
- Including a function that checks if LuanFile is located within another LuanFile (directory) at any level. My method can be used for the check.
- Including the combination 'toPath().toAbsolutePath().normalize().toString()' as 'absolute_path()' Luan function. 'Path.toRealPath()' can't be used, because it produces an exception if the file doesn't exist. 'File.getCanonicalPath()' can't be used because it resolves symbolic links.
- Including 'safe_site:' uri scheme that provides 'safe' file access. Perhaps throws an exception if forbidden file is accessed.