#pragma once #include #include struct lua_State; namespace mosis { class PathSandbox { public: explicit PathSandbox(const std::string& app_path); // Validate a path is within the sandbox // Returns true if valid, sets out_canonical to the resolved path bool ValidatePath(const std::string& path, std::string& out_canonical); // Check if path contains traversal attempts (..) static bool ContainsTraversal(const std::string& path); // Check if path is absolute static bool IsAbsolutePath(const std::string& path); // Normalize path separators and remove redundant ./ components static std::string NormalizePath(const std::string& path); // Validate module name for require() - alphanumeric, underscore, dots only static bool IsValidModuleName(const std::string& name); // Convert module name to relative path (e.g., "ui.button" -> "scripts/ui/button.lua") static std::string ModuleToPath(const std::string& module_name); // Get the app's base path const std::string& GetAppPath() const { return m_app_path; } // Resolve a relative path to full path within sandbox std::string ResolvePath(const std::string& relative_path); private: std::string m_app_path; }; // Safe require implementation for Lua // Loads modules only from app_path/scripts/.lua // Caches modules in registry int SafeRequire(lua_State* L); // Register safe require as global "require" // The PathSandbox pointer is stored in registry for use by SafeRequire void RegisterSafeRequire(lua_State* L, PathSandbox* sandbox); } // namespace mosis