FiveM implements a security sandbox for resources to ensure stability and prevent malicious code execution. This document describes the restrictions and allowed APIs within this sandbox environment.
All file system operations support two types of paths:
@resourceName/path
/absolute/path/to/resource
Resource mount paths are recommended as they're cleaner and more portable.
The io.readdir()
function returns files and folders within a directory:
-- Using mount paths (recommended)
local files1 = io.readdir("@myResource/")
local files2 = io.readdir("@myResource/assets")
-- Using absolute paths
local files3 = io.readdir("/absolute/path/to/resource")
local files4 = io.readdir("/absolute/path/to/resource/assets")
local files = io.readdir("@myResource/")
for _, file in ipairs(files) do
print(file) -- Process each file
end
-- Using mount paths (recommended)
local file1 = io.open("@myResource/data.json", "r")
-- Using absolute paths
local file2 = io.open("/absolute/path/to/resource/data.json", "r")
-- Available modes
"r" -- Read
"w" -- Write
"a" -- Append
"+" -- Create
Writing certain file types across resources is blocked to prevent code injection:
.lua
- Lua source files.dll
- Dynamic Link Libraries.ts
- TypeScript files.js
, .mjs
, .cjs
- JavaScript files.cs
- C# source filesNote: Writing these files is allowed within the same resource, but blocked across different resources.
The SaveResourceFile
native function follows these same restrictions.
New time measurement functions are available:
local nano = os.nanotime() -- Nanosecond precision
local micro = os.microtime() -- Microsecond precision
local delta = os.deltatime() -- Time difference
local tsc = os.rdtsc() -- Read Time-Stamp Counter
local tscp = os.rdtscp() -- Read Time-Stamp Counter and Processor ID
-- Blocked with "Permission denied" (code 13)
os.execute("command") -- All commands blocked
io.tmpfile() -- Temporary files blocked
io.popen(command .. resourcePath .. path .. suffix) -- Only emulated 'ls' and 'dir' allowed
-- Limited functionality
os.getenv("os") -- Returns "Windows" or "Linux"
os.setlocale() -- Returns current locale, cannot modify
-- These operations remain available
load() -- Not blocked
Enabling resource modifications or filesystem permissions can be dangerous if misused. Only enable these for resources you trust completely and understand their modifications.
To allow specific resources to write to other resources regardless of file extension restrictions, use the add_filesystem_permission
configuration:
-- Allow resourceA to write any file type to resourceB
add_filesystem_permission resourceA write resourceB
This override grants full write access, bypassing the default file extension restrictions. Please note that author names need to match to authorize write access.
To restrict ConVar access to specific resources, use the add_convar_permission
configuration:
-- Restrict reading of a ConVar to specific resources
add_convar_permission resourceA read some_convar_name
By default, ConVars are readable by all resources. Once a ConVar has at least one permission configured, it becomes restricted and only explicitly permitted resources can access it.