bmad-code-org/BMAD-METHOD · error · Error

--set "${entry}": '__proto__', 'prototype', and 'constructor

Error message

--set "${entry}": '__proto__', 'prototype', and 'constructor' are reserved and cannot be used as a module or key name.

What it means

Thrown by parseSetEntry when the module code or key is one of __proto__, prototype, or constructor (the PROTOTYPE_POLLUTING_NAMES set). parseSetEntries assigns overrides into plain-object maps keyed by user input; these names would mutate Object.prototype and cascade into every object lookup. Rejected at parse time as defense-in-depth — the maps are also Object.create(null).

Source

Thrown at tools/installer/set-overrides.js:58

  if (eq === -1) {
    throw new Error(`--set "${entry}": missing '='. Expected <module>.<key>=<value>`);
  }
  const lhs = entry.slice(0, eq);
  // Note: only the LHS is trimmed. Values may legitimately contain leading
  // or trailing whitespace (paths with spaces, quoted strings); module / key
  // names cannot, so it's safe to be strict on the left.
  const value = entry.slice(eq + 1);
  const dot = lhs.indexOf('.');
  if (dot === -1) {
    throw new Error(`--set "${entry}": missing '.'. Expected <module>.<key>=<value>`);
  }
  const moduleCode = lhs.slice(0, dot).trim();
  const key = lhs.slice(dot + 1).trim();
  if (!moduleCode || !key) {
    throw new Error(`--set "${entry}": empty module or key. Expected <module>.<key>=<value>`);
  }
  if (PROTOTYPE_POLLUTING_NAMES.has(moduleCode) || PROTOTYPE_POLLUTING_NAMES.has(key)) {
    throw new Error(
      `--set "${entry}": '__proto__', 'prototype', and 'constructor' are reserved and cannot be used as a module or key name.`,
    );
  }
  return { module: moduleCode, key, value };
}

/**
 * Parse repeated `--set` entries into a `{ module: { key: value } }` map.
 * Later entries overwrite earlier ones for the same key. Both the outer
 * map and the per-module inner maps are `Object.create(null)` so callers
 * that bypass `parseSetEntry`'s name check still can't pollute prototypes.
 *
 * @param {string[]} entries
 * @returns {Object<string, Object<string, string>>}
 */
function parseSetEntries(entries) {
  const overrides = Object.create(null);
  if (!Array.isArray(entries)) return overrides;

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Choose a module or key name that isn't __proto__, prototype, or constructor.
  2. If --set args are generated from external data, sanitize/reserved-filter upstream before passing them to the CLI.

Example fix

# before
#   --set module.constructor=y
#
# after
#   --set module.ctor=y
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED = new Set(['__proto__', 'prototype', 'constructor']);
function isSafeSetEntry(entry) {
  const eq = entry.indexOf('='); if (eq === -1) return false;
  const lhs = entry.slice(0, eq);
  const dot = lhs.indexOf('.'); if (dot === -1) return false;
  const mod = lhs.slice(0, dot).trim();
  const key = lhs.slice(dot + 1).trim();
  return !RESERVED.has(mod) && !RESERVED.has(key);
}
const entries = raw.filter(isSafeSetEntry);

Type guard

function isSafeSetEntry(entry) {
  const RESERVED = new Set(['__proto__', 'prototype', 'constructor']);
  if (typeof entry !== 'string') return false;
  const m = entry.match(/^([^.=]+)\.([^.=]+)=/);
  return !!m && !RESERVED.has(m[1]) && !RESERVED.has(m[2]);
}

Try / catch

try {
  overrides = parseSetEntries(entries);
} catch (e) {
  if (/reserved and cannot be used/.test(e.message)) {
    // drop the offending entry; it's either hostile input or a naming mistake
  } else { throw e; }
}

Prevention

When it happens

Trigger: Passing --set __proto__.x=1, --set module.constructor=y, or --set prototype.key=val. Any override whose module or key segment equals one of the reserved names.

Common situations: Adversarial/fuzzed CLI input; a generated script feeding arbitrary strings as keys; misunderstanding the format and using a JS built-in as a name; attempting prototype pollution deliberately (this is the guard working).

Related errors


AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13). Data as JSON: /api/errors/1171e610766dbeb3. Report an issue: GitHub.