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
| Removed | Why |
|---|---|
io, package, debug, dofile, loadfile, string.dump | No 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 text | You can load("return 1 + 1"), but not binary chunks or functions. |
require of anything outside the folder | require("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:
| What | Limit |
|---|---|
Loading (main.lua running the first time) | 3 seconds |
| An event handler, timer, button click or other callback | 250 ms |
| One chat line through middleware | 400 ms (and the whole batch of chat waits at most 1.5 seconds for all plugins) |
| A line you type into the console | 2 seconds |
| Memory | 64 MB |
The size of main.lua | 2 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
| What | Limit |
|---|---|
| Event handlers / timers per plugin | 200 / 200 |
| Windows open at once | 6 |
| Dashboard sections | 10 |
| One interface | 2,000 elements, 24 levels deep, about 400 KB |
| One piece of text in an interface | 20,000 characters |
| Storage | 1 MB and 5,000 keys |
| Web requests | 8 waiting, 30 a minute, 1 MB out, 2 MB back |
| A message to another plugin | 64 KB |
| Console | the 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.

