Skip to main content

Bot Module Security

Bot modules execute third-party code that can send chat messages and perform moderation actions. Lumio enforces multiple security layers to protect streamers, viewers, and the platform.

V8 isolation

Every handler invocation runs inside an isolated V8 sandbox with strict resource limits:

LimitSync path (commands, moderation)Async path (keywords, patterns, events, timers)
CPU timeout500ms10s
Memory256 MB heap256 MB heap
Response size4 MB4 MB

Each extension install gets its own V8 isolate. Isolates share no state — one extension cannot access another extension's memory, variables, or closures.

Database isolation

Each extension install gets its own PostgreSQL schema (ext_\{install_id\}). Extensions cannot query core Lumio tables (users, accounts, overlays) or other extensions' schemas.

Cache isolation

ctx.cache operations are scoped to ext-cache:\{install_id\}:* in Redis. The Rust worker prepends this prefix before executing any Redis command. Extensions cannot access other extensions' cache keys or any internal Lumio Redis keys.

Egress restrictions

ctx.fetch() only allows HTTPS requests to hostnames declared in the egress.allowHosts manifest field. Private IP ranges (10.*, 172.16-31.*, 192.168.*, 127.*, link-local) are blocked at two layers:

  1. URL hostname check — literal IP addresses in the URL are rejected
  2. Post-DNS-resolution check — after DNS resolution, every resolved IP is validated against private ranges, preventing DNS rebinding attacks

Redis isolation

Extension JavaScript has no direct Redis access. There is no ctx.redis API. All Redis operations (ctx.cache, cooldowns, rate limits, pub/sub) are performed by trusted Rust code in the Worker. Redis keys are constructed from validated install IDs — extension input is never interpolated into key names.

Permission tiers

Extensions declare required permissions in lumio.config.json. Each permission goes through store review:

PermissionReview levelNotes
chat:readStandardReading chat messages
chat:sendStandardSending chat replies
events:readStandardReceiving platform events
chat:deleteEnhanced manual reviewDeleting chat messages
chat:banEnhanced manual reviewBanning or timing out users

Extensions requesting chat:ban or chat:delete undergo additional manual code review during the store approval process. Reviewers verify that moderation logic is sound and that the extension cannot be exploited to mass-ban or mass-delete.

Rate limits

All actions are rate-limited per installation to prevent abuse:

Handler invocation limits

CategoryLimitScope
Command execution60/minPer install
Keyword/pattern execution100/minPer install
Event handler execution50/minPer install
Timer execution1/intervalPer install

Action output limits

ActionLimitScope
Chat send30/minPer install
Ban5/minPer install
Timeout10/minPer install
Delete message20/minPer install
Cache operations200/minPer install

Rate limits are enforced at two layers:

  1. Input: Limits how often a handler is invoked
  2. Output: Limits what actions the handler can produce, regardless of which handler type generated them

A keyword handler that returns a ban action is still subject to the 5/min ban limit. This prevents bypassing moderation rate limits by splitting actions across handler types.

Trigger limits

Each extension is limited in how many triggers it can declare:

Trigger typeMaximum per extension
Commands20
Keywords50
Patterns (regex)10
Keyword minimum length3 characters
Pattern maximum length200 characters

Regex patterns are validated for safety. The Rust regex crate guarantees linear-time matching (no backreferences or lookaheads), making ReDoS attacks impossible by construction. Pattern matching runs in Rust on the bot side — JavaScript RegExp is never used for trigger matching.

Moderation fail-closed policy

When the sync moderation path times out (500ms), the bot applies a configurable default policy:

PolicyBehavior
allow (default)Message passes through
holdMessage is held and auto-deleted after 5 seconds if no response

The policy is configured per account in bot module settings, not per extension. Most streamers use allow to avoid false positives from slow responses.

Audit log

Every moderation action executed by a bot module extension is logged to the platform audit log with:

  • Source: extension:\{install_id\}
  • Metadata: Extension name, extension ID, handler name
  • Action: The specific moderation action (ban, timeout, delete)
  • Reason: Prefixed with the extension name for traceability

Account owners can view extension-originated moderation actions separately from manual and built-in module actions in the dashboard audit log.

Kill switch

Every account has a "Pause all extension modules" toggle in the dashboard. When activated:

  1. A signal is published to all connected bots and the Worker
  2. All extension bot module processing stops immediately for that account
  3. All pending deferred jobs for that account are cancelled immediately
  4. Built-in modules (link protection, word filter, spam protection) continue operating normally

The kill switch is designed for emergencies — if a malicious extension starts banning legitimate users, the streamer can stop all extension modules with one click.

Built-in module priority

Built-in modules (LinkProtection, WordFilter, SpamProtection) always run before extension modules. If a built-in module blocks a message, extension moderate() handlers are not invoked. Built-in modules execute in under 1ms with no V8 overhead.

Error isolation

Handler errors are contained within the isolate:

ScenarioBehavior
Handler throws an exceptionError logged, no message sent to chat
Handler times out (sync)Command silently dropped, moderation applies default policy
Handler times out (async)Handler killed, error logged
Handler returns invalid dataTreated as null response, warning logged
ctx.db errorPromise rejects inside handler
ctx.fetch blockedPromise rejects with EgressDenied error
Rate limit exceededHandler not invoked, message silently dropped