Skip to content

fix(resolve): stop an Object.prototype name resolving as an engine or tool#48

Merged
ralyodio merged 1 commit into
moshcoder:mainfrom
clawedassistant26:fix/prototype-key-resolves-as-target
Jul 26, 2026
Merged

fix(resolve): stop an Object.prototype name resolving as an engine or tool#48
ralyodio merged 1 commit into
moshcoder:mainfrom
clawedassistant26:fix/prototype-key-resolves-as-target

Conversation

@clawedassistant26

Copy link
Copy Markdown
Contributor

Bug

ENGINES, ALIASES, TOOLS and AI_EXEC are plain object literals looked up with OBJ[key]. A target name that happens to be an Object.prototype member therefore resolves truthy and is passed on as a real entry — one with no bin and no install spec.

Reproduced on main (05cfd7f), every entrypoint:

$ moshcode install constructor
TypeError: Cannot read properties of undefined (reading 'cmd')
    at main (bin/moshcode.mjs:233:65)

$ moshcode upgrade constructor
TypeError: Cannot read properties of undefined (reading 'installed')   # planUpgrade → resolveTool

$ moshcode constructor                                                # tool passthrough
TypeError [ERR_INVALID_ARG_TYPE]                                       # openTool with bin undefined

mosh ▸ /install constructor
TypeError: Cannot read properties of undefined (reading 'cmd')
    at installTarget (src/tui.mjs:257:59)

In the TUI this is the worst case: the crash takes the whole pit down, so the session, its history and its cwd go with it, where the code clearly meant to print unknown engine or tool "constructor" and carry on. __proto__ behaves the same way (names are lowercased first, so constructor and __proto__ are the ones that reach these lookups).

It is not only a typo path: moshscript scripts call install(name) / upgrade(name) / ai(p, {engine}) with strings the script computed, so an unvalidated value lands here as a stack trace rather than the tool's own error message.

Fix

Resolve own properties only, so these names fall through to the existing usage / unknown-target branches that were already written for them:

  • src/engines.mjsresolveEngine, aiExecArgs, pickAiEngine
  • src/tools.mjsresolveTool
  • src/tui.mjsinstallTarget
  • bin/moshcode.mjs — the install target lookup

moshcode upgrade needed no change of its own: it goes through resolveEngine/resolveTool. No behaviour change for any real engine, alias or tool name.

Tests

4 added, each stash-verified against unpatched src/+bin/ (all 4 fail there, all 4 pass with the fix):

  • test/engines.test.mjsresolveEngine/pickAiEngine/aiExecArgs reject the prototype names
  • test/tools.test.mjsresolveTool rejects them, plus an end-to-end moshcode install constructor that must exit 1 with usage and no TypeError
  • test/tui.test.mjs/install constructor prints the unknown-target line and the pit survives to /quit

Full suite: node --test159 pass / 0 fail (main: 155).

… tool

ENGINES, ALIASES, TOOLS and AI_EXEC are plain object literals looked up with
OBJ[key], so a target named after an Object.prototype member resolved truthy
and was handed downstream as a real entry with no bin or install spec.

  $ moshcode install constructor
  TypeError: Cannot read properties of undefined (reading 'cmd')

Same crash from `moshcode upgrade constructor`, `moshcode constructor`
(passthrough), and `/install constructor` in the TUI, where it takes the
whole session down instead of printing the unknown-target line.

Resolve own properties only, so these names fall through to the existing
usage/unknown-target paths.
@ralyodio
ralyodio merged commit 3673d3e into moshcoder:main Jul 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants