Skip to content
ForgeCastDocs

The sandbox and its limits

What a plugin can't do, how its time and memory are limited, and why one broken plugin can't hurt ForgeCast or another plugin.

A plugin is code written by someone, run on your streaming PC while you are live. ForgeCast treats it that way: every plugin lives in a small sandbox, can only do what its person approved, and is stopped when it misbehaves.

What a plugin is

Each plugin runs in its own Lua 5.4 state on its own thread. It doesn't share variables with other plugins, and a plugin that crashes, loops forever or runs out of memory is stopped on its own; ForgeCast and the other plugins carry on. The only ways in and out are the functions in the API reference, each checked against the permissions the person approved.

What is left out of Lua

RemovedWhy
io, package, debug, dofile, loadfile, string.dumpNo files, no loading code from elsewhere, no poking at the interpreter.
os.execute, os.exit, os.remove, os.getenv, …No running programs, no environment. Only os.time, os.date, os.clock and os.difftime remain.
load of anything but textYou can load("return 1 + 1"), but not binary chunks or functions.
require of anything outside the folderrequire("name") reads .lua files inside the plugin's own folder, nothing else. A file outside it (even through a shortcut) is refused.

You still have the normal Lua you know: string, table, math, utf8, coroutine, closures, metatables, pcall, and string.format.

Time and memory

A plugin never gets to hold ForgeCast up. Every piece of its code runs against a clock:

WhatLimit
Loading (main.lua running the first time)3 seconds
An event handler, timer, button click or other callback250 ms
One chat line through middleware400 ms (and the whole batch of chat waits at most 1.5 seconds for all plugins)
A line you type into the console2 seconds
Memory64 MB
The size of main.lua2 MB

When code runs over, it is stopped with a message that says how long it ran and where (the plugin ran for more than 250 ms in one go and was stopped), the console shows it, and the plugin carries on with whatever is next. If loading runs over, or main.lua has an error, the plugin doesn't start and says why. Chat middleware that is too slow (or broken) is skipped, so chat keeps flowing: the line goes through unchanged.

Loops that wait don't work, and shouldn't: while true do end is stopped at once. To do something later or regularly, use timers. To wait for a website, give http a callback.

Other limits

WhatLimit
Event handlers / timers per plugin200 / 200
Windows open at once6
Dashboard sections10
One interface2,000 elements, 24 levels deep, about 400 KB
One piece of text in an interface20,000 characters
Storage1 MB and 5,000 keys
Web requests8 waiting, 30 a minute, 1 MB out, 2 MB back
A message to another plugin64 KB
Consolethe last 2,000 lines are kept; lines past 300 in one second are dropped (and the console says how many)

What the person is protected from

  • Nothing runs until it is approved, and only what was ticked. A plugin that wants more after an update has to ask again.
  • A plugin can't draw anything it likes. Its interface is data, drawn with ForgeCast's own components: no HTML, no CSS, no scripts. Links and pictures have to be https. A window a plugin opens has no network access and no account access.
  • The internet is fenced. Only https, only public addresses: nothing on your computer or your network can be reached, and the headers that matter are set by ForgeCast.
  • One plugin can't read another's data, and can't impersonate it on the plugin bus (messages say who they are from).
  • A broken plugin shows its error with a traceback in its console instead of failing silently.

What it doesn't protect from

A sandbox keeps a plugin from harming your computer. It can't tell whether a plugin does what its description says with the things you let it see.

Only install plugins you trust

A plugin with chat.read and network can send every chat message to a website. A plugin with chat.middleware sees every line before you do and can hide or change it. ForgeCast shows exactly what a plugin asks for, and marks network and app.open_url as Be careful; read the list, and keep to plugins whose author you know. There is no plugin store yet: plugins are folders, shared as a zip or a repository.

On this page