Skip to main content
← Back to list
01Issue
BugClosedSwamp CLIPublic
AssigneesNone

Relationships

#3287 Extension safety scanner rejects .eval() method calls, blocking @swamp/stagecraft install

Opened by magistr · 10/12/2026

Summary

swamp extension pull aborts on any file containing the substring eval(, without checking whether it is a call to the global eval. This currently makes the official @swamp/stagecraft extension impossible to install, because its bundled studio frontend embeds swamp's own CEL expression interpreter — whose AST-dispatch method is named eval.

A safety check is rejecting swamp's own official extension for containing swamp's own evaluator.

Reproduction

swamp extension pull @swamp/stagecraft

Result:

Error: Extension has safety errors. Install aborted.
  .../extension/models/_lib/engine/studio_asset_app.ts:
  File contains eval() or new Function() which are not allowed.

Reproduces on a freshly upgraded repo. No CLI flag bypasses it: neither extension pull nor extension install exposes a safety override, and extension trust add swamp does not help (trust governs auto-resolution, not this scanner).

Evidence that the finding is a false positive

stagecraft/extensions/models/_lib/engine/studio_asset_app.ts is a 12-line file wrapping a ~785 KB minified frontend bundle. Analysing the bundle text:

pattern count
calls to global eval(...) 0
new Function 0
method calls .eval(...) 32
method declaration eval(t,n){...} 1

The single hit not preceded by . is a class method definition, not a call:

eval(t,n){ return t.evaluate(this,t,n) }

Its body is tree-walking interpreter dispatch. Interpreter identifiers present in the bundle confirm the provenance: CelNamespace, registerFunctionOverload, optional.orValue, accuValue, no_such_overload.

So there is no dynamic code evaluation in this file at all.

Root cause

The scanner appears to match the bare substring eval(. It needs to exclude matches preceded by . or by an identifier character, and to distinguish a method declaration from a call. A regex along the lines of

(?<![.\w$])eval\s*\(

removes 32 of the 33 matches here; excluding method-definition position removes the last one.

Impact

  • @swamp/stagecraft (official, repository-verified, v2026.10.12.2) cannot be installed at all on swamp 20260930.234450.0.
  • Any extension bundling an interpreter, VM, or expression evaluator that names a method eval is unconditionally blocked, with no override.

Suggested fix

Require a word boundary and no leading ./identifier character before eval( when scanning. Separately, consider an explicit, auditable override for reviewed-and-accepted findings, so a false positive is not a hard stop.

Environment

  • swamp CLI: 20260930.234450.0-sha.657fe527
  • repo swampVersion: 20260930.234450.0 (after swamp repo upgrade)
  • platform: darwin 23.6.0 (arm64), zsh
  • extension: @swamp/stagecraft v2026.10.12.2
02Bog Flow
✓OPEN○TRIAGED○IN PROGRESS◉CLOSED

Closed

10/12/2026, 2:47:27 PM

No activity in this phase yet.

03Sludge Pulse
Editable. Press Enter to edit.

magistr commented 10/12/2026, 2:36:45 PM

Found in the same session as #3288 (swamp repo upgrade not removing superseded skills). The two are independent defects filed separately; noting the link because #3288 was initially attempted as a workaround for this issue — upgrading the repo does not change the scanner, since the CLI binary was already at 20260930.234450.0.

magistr commented 10/12/2026, 2:47:27 PM

No longer reproduces on swamp 20261012.141205.0-sha.58191ab3 — closing.

Confirmed the fix is in the CLI, not the extension:

  • Same extension version as the failing run: @swamp/stagecraft v2026.10.12.2 (registry updatedAt 2026-10-12T07:37:45Z, unchanged).
  • The installed models/_lib/engine/studio_asset_app.ts still contains the .eval( pattern that previously tripped the scanner.
  • swamp extension pull @swamp/stagecraft now completes and installs all four model types (factory, work-item, studio, tracker) plus the reports and skill.

So the scanner change in 20261012.141205.0 resolved it. Apologies for the noise if this was already fixed in-flight when I filed — my binary was 20260930.234450.0 at the time. Reopen if the underlying substring match is still present and only the stagecraft case was special-cased.

Sign in to post a ripple.