Skip to Content
ReferenceSandbox & Permissions

Work within the resource sandbox

A resource is not an unrestricted operating-system process. The pinned sandbox manual  defines filesystem, OS and permission boundaries. Keep application validation even when the runtime blocks an operation: a permitted write can still overwrite valuable data inside the resource.

Paths, writes and directory handles

Use @resourceName/path mount paths for portability. Absolute resource paths are also documented, but an absolute path does not bypass access control. Own-resource writes are allowed. Cross-resource writes are denied for all file types unless an explicit permission grants access. SaveResourceFile follows the same restrictions as the filesystem API.

The server’s main directory, locations outside resource folders, .. traversal and symlink following/creation are blocked. A rejected operation can report code 13, “Permission denied.” Do not retry by constructing a different escape path or granting administrator access to the server process.

io.readdir() returns a directory handle, not an array. Iterate through its :lines() method and close it after use. This server-side diagnostic lists only the current resource and handles failure without publishing filesystem paths to clients:

-- server.lua; run inside a FiveM resource, not standalone Lua. RegisterCommand('doclistfiles', function(source) if source ~= 0 then return end local ok, directory = pcall(io.readdir, '@' .. GetCurrentResourceName() .. '/') if not ok or not directory then print('Resource directory could not be opened.') return end local listed = pcall(function() for name in directory:lines() do print(name) end end) directory:close() if not listed then print('Directory listing was interrupted.') end end, false)

For io.open, the source describes read (r), write (w) and append (a) operations. Its shorthand mention of + is not a complete replacement for Lua’s mode syntax; use the documented combined mode required by your runtime and check the return value. Writing can truncate an existing file. Prefer a fixed owned data filename and validated JSON rather than client-controlled path fragments. The storage guide covers application-level handling.

OS API boundaries

APIDocumented boundary
os.executeCommand execution is blocked with permission denied.
io.tmpfileTemporary-file creation is blocked.
io.popenOnly emulated ls and dir operations are allowed; this is not a general shell, pipe or command-substitution facility. Prefer io.readdir.
os.getenv("os")Reports the documented platform values Windows or Linux; do not treat it as arbitrary environment-variable access.
os.setlocaleCan return the locale, not change it.
loadAvailable. That does not make evaluating untrusted strings safe.
os.nanotime, os.microtime, os.deltatimeAdditional timing facilities. The source’s brief descriptions do not specify a portable epoch or a cross-machine clock contract.
os.rdtsc, os.rdtscpProcessor-counter facilities; the latter also reports processor information. Do not turn a CPU counter into a persistent timestamp or authentication token.

Do not silently monkey-patch filesystem access globally to make an incompatible dependency appear supported. First identify its failing operation, inspect the current supported runtime, and choose a supported library configuration or an external service boundary. Keep the sandbox enabled during diagnosis.

Explicit permissions are administrator decisions

These are server configuration directives, not Lua API calls. Resource names and convar names in the examples are illustrative. Do not paste all permissions into a production configuration as a generic fix.

# Optional cross-resource write grant, only for a reviewed requirement: add_filesystem_permission trusted_importer write owned_target # First grant makes this convar readable only by explicitly permitted resources: add_convar_permission trusted_backend read private_service_key # Separate unsafe capabilities; leave absent unless specifically required: # add_unsafe_worker_permission "trusted_backend" # add_unsafe_child_process_permission "trusted_backend"

A filesystem grant gives the source resource full write access to the target resource. It is broader than permitting one harmless JSON field. Review who supplies and updates both resources and whether separate data ownership would remove the need for the grant.

Convars are normally readable by resources. Once at least one add_convar_permission applies to a convar, only its explicitly allowed resources can read it. Test both permitted and unpermitted resources. This permission is not a reason to replicate a secret with setr or advertise it with sets; see convar transport and exposure.

Worker creation and child-process creation are separately restricted by default. The two unsafe permission directives are opt-ins, not substitutes for routine application code. Review the exact process, executable arguments, lifecycle, resource limits and trust boundary before enabling either one. The sandbox document does not establish that every other blocked Lua OS API becomes available as a side effect.

Verify and roll back

On a disposable server, test an own-resource write, a denied cross-resource write, a denied traversal, and the intended narrow grant. Back up target data before enabling writes. Verify that an unpermitted resource cannot read an allowlisted convar; never print its secret value to prove the test.

For rollback, remove the explicit grant from the managed configuration, perform a controlled server restart and repeat the negative checks. Do not invent an undocumented remove_* console command. Resource restarts alone are not evidence that configuration-level permissions were revoked. This page’s example and acceptance matrix are documentation, not a claim that your runtime has already passed them.