# How FileMgr Sandboxes File Access for Lua Scripts in YimMenuV2

> Learn how YimMenuV2's FileMgr sandboxes Lua file access, restricting operations to the scripts directory and preventing path traversal attacks.

- Repository: [YimMenu/YimMenuV2](https://github.com/YimMenu/YimMenuV2)
- Tags: how-to-guide
- Published: 2026-07-17

---

**YimMenuV2 confines all Lua file operations to a dedicated `./scripts` directory by validating every path through the `FileMgr` library, rejecting traversal attempts using `../` or absolute paths with a clear Lua error.**

The `FileMgr` system in YimMenuV2 provides Lua scripts with essential filesystem capabilities while enforcing strict security boundaries. Implemented in [`src/core/scripting/libraries/FileMgr.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/scripting/libraries/FileMgr.cpp), this sandbox ensures user scripts interact only with files inside a designated scripts folder, preventing unauthorized access to sensitive host system locations.

## Defining the Sandbox Boundary

### The Scripts Root Directory

The sandbox establishes a single canonical root for all file activity. The `ScriptsRoot()` function returns an absolute path pointing to `./scripts` within the project folder, obtained via `YimMenu::FileMgr::GetProjectFolder("./scripts")`. This location represents the exclusive zone where Lua scripts may read, write, or modify files.

### Path Validation Pipeline

Before any filesystem operation executes, the engine subjects the requested path to a rigorous two-stage validation:

1. **String Safety Check**: The input first passes through `CheckStringSafe` (provided in [`src/core/scripting/LuaUtils.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/scripting/LuaUtils.cpp)) to ensure safe string handling.
2. **Sandbox Resolution**: The `ResolveInSandbox` function canonicalizes the path using `std::filesystem::weakly_canonical` and computes its lexical relationship to `ScriptsRoot()`.

## Core Validation Implementation

### ResolveInSandbox Function

Located in [`src/core/scripting/libraries/FileMgr.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/scripting/libraries/FileMgr.cpp) between lines 22-47, the `ResolveInSandbox` function implements the core security logic:

```cpp
static bool ResolveInSandbox(std::string_view input, std::filesystem::path& out) {
    if (input.empty()) return false;
    std::filesystem::path p(std::string{input});
    std::error_code ec;
    auto canon = std::filesystem::weakly_canonical(p, ec);
    if (ec) return false;
    auto rel = canon.lexically_relative(ScriptsRoot());
    std::string rel_str = rel.generic_string();
    if (rel_str.empty() || rel_str == "." || rel_str.starts_with(".."))
        return false;                       // outside sandbox
    out = canon;
    return true;
}

```

This function rejects paths where canonicalization fails or where the resulting relative path indicates traversal above the scripts root.

### CheckSandboxedPath Wrapper

The `CheckSandboxedPath` function (lines 49-58) serves as the uniform entry point for all file operations exposed to Lua. It invokes `ResolveInSandbox` and, upon validation failure, aborts execution with `luaL_argerror(state, idx, "path is outside the script sandbox")`, immediately terminating the offending script.

## Sandboxed API Methods

Every public function in the `FileMgr` Lua library applies `CheckSandboxedPath` before accessing the filesystem:

- **CreateDir(path)**: Creates directories (including parent directories) after sandbox verification.
- **DeleteFile(path)**: Removes files only after confirming the target lies within the scripts folder.
- **DoesFileExist(path)**: Returns existence status restricted to the sandbox boundary.
- **FindFiles(dir, ext, recursive)**: Searches exclusively within the allowed directory tree.
- **ReadFileContent(path)**: Reads file contents post-validation.
- **WriteFileContent(path, data, append?)**: Writes or appends data only following successful path verification.

## Practical Usage Examples

The following Lua code demonstrates successful sandboxed operations and failed escape attempts:

```lua
-- Successful operations inside the sandbox
FileMgr.CreateDir("my_mod/data")                -- creates ./scripts/my_mod/data
local ok = FileMgr.WriteFileContent("my_mod/data/config.txt", "enabled=true")
print("Write succeeded:", ok)

-- Attempt to escape the sandbox (raises a Lua error)
-- This triggers: path is outside the script sandbox
FileMgr.ReadFileContent("../outside.txt")

```

## Summary

- **Isolation Root**: All Lua file operations are restricted to the `./scripts` folder returned by `ScriptsRoot()`.
- **Validation Layer**: `CheckSandboxedPath` and `ResolveInSandbox` in [`FileMgr.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/FileMgr.cpp) enforce the boundary using `std::filesystem` canonicalization.
- **Traversal Prevention**: Any path resolving outside the root—whether via `../`, absolute paths, or empty strings—triggers an immediate Lua error.
- **Universal Coverage**: Every exposed `FileMgr` function (read, write, delete, search) applies identical sandbox checks before execution.

## Frequently Asked Questions

### What happens if a Lua script tries to access a file outside the scripts folder?

The `CheckSandboxedPath` function detects the traversal attempt during the `ResolveInSandbox` check and calls `luaL_argerror` with the message `"path is outside the script sandbox"`, immediately halting the script execution and preventing the file operation.

### Can Lua scripts use absolute paths within the FileMgr sandbox?

No. Even absolute paths are canonicalized and checked against the `ScriptsRoot()`. If the canonicalized absolute path does not resolve to a location inside the `./scripts` directory, the operation is rejected regardless of whether an absolute or relative path was provided.

### Where is the sandbox root directory located in YimMenuV2?

The sandbox root is located at `./scripts` relative to the YimMenuV2 project folder, obtained programmatically via `YimMenu::FileMgr::GetProjectFolder("./scripts")`. This path is calculated once and serves as the authoritative boundary for all subsequent file access validation.

### Does the FileMgr sandbox allow recursive directory creation?

Yes. The `CreateDir` function supports creating nested directory structures (similar to `mkdir -p`) as long as the resulting path remains within the `./scripts` folder. Parent directories are created automatically if they do not exist, provided the entire path chain stays inside the sandbox boundary.