Bytecode Breakdown: Unraveling Factorio's Lua Security Flaws
Scope of the Exploit & Lua Bytecode Design
- Exploit hinges on Factorio allowing loading of raw Lua bytecode from untrusted sources (servers/mods).
- Commenters stress that Lua’s bytecode was designed for execution speed, not static safety verification.
- Some compare this to giving web pages access to a JS engine’s internal bytecode rather than JS source.
- Several note that Lua’s own docs already warn that loading untrusted binary chunks is unsafe.
Bytecode vs JIT and Verifiability
- Debate over conflating bytecode with JIT:
- One side argues JIT adds extra attack surface (RWX memory, speculation issues, Spectre/Meltdown).
- Others point out this exploit is purely about malicious bytecode, not JIT.
- Examples like JVM, .NET, WASM, and BPF are cited as “designed-to-be-verifiable” bytecodes.
- Discussion on how much easier static verification is for simpler, stack-based or strongly-typed bytecodes versus Lua’s design.
Factorio’s Response and Responsibility
- Links to Factorio commits show remediation: essentially disabling bytecode loading and tightening APIs like
load. - Some are surprised Factorio implemented its own verifier despite upstream abandoning one as too hard.
- There is criticism of “security through obscurity” when changes weren’t clearly documented; others note most players auto-update anyway.
Sandboxing Lua and Best Practices
- Strong consensus: never allow untrusted Lua bytecode; only accept source.
- Common advice: disable debug, IO, OS libraries; be very cautious about sandboxing in general.
- Historical parallels from other games (Roblox, Garry’s Mod, Company of Heroes) show repeated failures around Lua bytecode and sandboxes.
- Luau is cited as an example that bans untrusted bytecode and provides stronger sandboxing guarantees.
Game Architecture, Multiplayer, and Isolation
- Factorio syncs simulation by replaying inputs on all clients, so Lua scripts must run identically everywhere; syncing only results would explode bandwidth.
- Some suggest Firecracker-like VM or strong OS-level isolation for untrusted code, but portability and performance are concerns.
- Broader sentiment: treat networked games as insecure clients; consider isolating gaming machines or sandboxes.
Why Lua Instead of JavaScript?
- Lua is seen as much easier to embed, with a small, integration-focused design.
- JS engines (especially browser ones) are considered heavier, more complex, and historically harder to integrate, despite their stronger hardening.