different-ai/openwork · error · InterpreterRuntimeError

Property '${key}' is not available in CodeMode.

Error message

Property '${key}' is not available in CodeMode.

What it means

guardedSet is used by Object.assign and Object.fromEntries in CodeMode to block writing properties whose keys match isBlockedMember (a denylist of dangerous names like __proto__, constructor, prototype). Writing such a key throws this error to prevent prototype-pollution-style attacks inside the sandbox.

Source

Thrown at packages/codemode/src/stdlib/object.ts:19

import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
import { isBlockedMember } from "../tool-runtime.js"
import { isSandboxValue, SandboxMap, SandboxURLSearchParams } from "../values.js"
import { boundedData, coerceToString } from "./value.js"

export const objectStatics = new Set(["keys", "values", "entries", "hasOwn", "assign", "fromEntries"])

export const invokeObjectMethod = (name: string, args: Array<unknown>, node: AstNode): unknown => {
  if (!objectStatics.has(name)) throw new InterpreterRuntimeError(`Object.${name} is not available in CodeMode.`, node)
  const requireObject = (): Record<string, unknown> => {
    const value = boundedData(args[0], `Object.${name} input`)
    if (isSandboxValue(value)) return {}
    if (value === null || typeof value !== "object" || Array.isArray(value)) {
      throw new InterpreterRuntimeError(`Object.${name} expects a data object.`, node)
    }
    return value as Record<string, unknown>
  }
  const guardedSet = (out: Record<string, unknown>, key: string, item: unknown): void => {
    if (isBlockedMember(key)) throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, node)
    out[key] = item
  }
  switch (name) {
    case "keys": {
      const value = boundedData(args[0], "Object.keys input")
      if (isSandboxValue(value)) return []
      if (Array.isArray(value)) return Object.keys(value)
      if (value === null || typeof value !== "object") {
        throw new InterpreterRuntimeError("Object.keys expects a data object or array.", node)
      }
      return Object.keys(value)
    }
    case "values":
      return Object.values(requireObject())
    case "entries":
      return Object.entries(requireObject()).map(([key, item]) => [key, item])
    case "hasOwn":
      return Object.hasOwn(requireObject(), String(args[1]))

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Sanitize input keys before calling assign/fromEntries: drop or rename keys matching /^( __proto__|constructor|prototype)$/
  2. Use a prefix or namespaced keys for untrusted data, e.g. store as meta['field'] instead of raw keys
  3. Filter pairs: pairs.filter(([k]) => k !== '__proto__' && k !== 'constructor' && k !== 'prototype')
  4. If the key is legitimately needed, transform it (e.g. underscore prefix) before constructing the object

Example fix

// before
const merged = Object.assign({}, userInput)
// after
const safe = Object.fromEntries(
  Object.entries(userInput).filter(([k]) => !['__proto__','constructor','prototype'].includes(k))
)
const merged = Object.assign({}, safe)
Defensive patterns

Strategy: validation

Validate before calling

const BLOCKED = new Set(['__proto__','constructor','prototype'])
const sanitized = Object.fromEntries(
  pairs.filter(([k]) => !BLOCKED.has(String(k)))
)

Try / catch

try {
  return Object.assign({}, untrusted)
} catch (e) {
  if (e instanceof InterpreterRuntimeError && e.message.includes("is not available in CodeMode") && e.message.includes("Property")) {
    return Object.assign({}, filterBlockedKeys(untrusted))
  }
  throw e
}

Prevention

When it happens

Trigger: Object.assign(target, {__proto__: x}), Object.fromEntries([['__proto__', {}]]), Object.fromEntries([['constructor', fn]]), or merging user/API-supplied key/value data that contains keys named __proto__, prototype, or constructor.

Common situations: Merging untrusted API/JSON payloads into config objects where a payload key collides with a blocked name; CSV/JSON ingest where a column is literally named __proto__.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/bf60cda758a63db9. Report an issue: GitHub.