Dicey Table

Scanner rule codes

Five whole-word regular expressions are run over raw script text. A match on any one of them is a severity: "error" issue carrying the code below, and it stops the mod being registered or served. They are declared as bannedScriptPatterns in packages/shared/src/modManifest.ts and mirrored as SANDBOX_SCANNER_RULES in apps/server/src/githubScanner.ts.

These five are the script-content codes. The scanner emits many more codes for paths, assets, media, manifests, JSON, packs and dependency graphs — What gets rejected is the complete list, and Fixing a rejection is the per-code repair guide. This page is the value table for the five that read your code.

The values#

Code Tokens that reject the file Message Contexts it is checked in Surfaces it applies to
dom-access document window parent top opener Scripts cannot access DOM/window globals. GitHub scan · serve time · local editor draft Mod entry.script and compiled table scripts
network-access fetch XMLHttpRequest WebSocket EventSource Scripts cannot open arbitrary network connections. the same three both
storage-access localStorage sessionStorage indexedDB cookie Scripts cannot access browser storage or cookies. the same three both
dynamic-code eval Function importScripts Scripts cannot use dynamic code loading. the same three both
timer-loop setInterval requestAnimationFrame Scripts must be deterministic and event-driven. the same three both

Every pattern is case-sensitive: Function is banned and function is fine; Top is fine and top is not.

The two facts that catch people#

Comments are scanned. There is no lexer and no parse — the regex runs over raw text, so a comment, a string literal and an identifier are indistinguishable. // draw the top card rejects the file.

Table scripts are scanned too. validateSceneScriptSafety runs the same five patterns over a scene script's compiled body, and the editor's transpile does not strip comments, so the same comment rejects a whole scene.

By design. The scanner's own note states the trade: "false positives are acceptable (mod authors can adjust scripts), while false negatives are treated as boundary risks and should trigger a rule update." This is a security boundary and it is not expected to loosen. \b needs a non-word character on both sides, so topCard, deckTop, parentZone, parentId, fetchCount and windowSeat are all safe — rename or rephrase. Per-rule workarounds are on Script safety. See Known limitations.

The one that cost a real feature, and what was done about it#

dom-access includes the bare word top, and three of the nine screen anchors a mod can give a UI element are "top-left", "top-center" and "top-right". Because " and - are both non-word characters, the word boundary fires inside the string, so a mod script containing any of those three was rejected outright.

The rule was not changed. Matching inside string literals is what makes it useful — it is what catches self["top"] — and narrowing it would swap a false positive for a false negative, which the scanner's own note calls the unacceptable direction. Instead presentation.anchor gained three input aliases: upper-left, upper-center and upper-right, normalized to the canonical top-* values before anything is stored. Write the alias in a mod script and read the canonical value back. See TableUiWidgetType.

Where else these five appear#

The same five patterns are what undeclared-capability is not: capability validation is a separate check with its own twelve detector regexes and its own code. A script can pass all five patterns and still be rejected for calling an api method its manifest did not declare. See Mod capabilities.

See also#