{"record":{"id":"3aea20625b320bda","repo":"affaan-m/ECC","slug":"refusing-to-invoke-an-it-cli-shim-set-executab","errorCode":null,"errorMessage":"Refusing to invoke an Itô CLI shim. Set ${EXECUTABLE_OVERRIDE} to the absolute dist/bin/ito.js path.","messagePattern":"Refusing to invoke an Itô CLI shim\\. Set (.+?) to the absolute dist/bin/ito\\.js path\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/ito.js","lineNumber":257,"sourceCode":"      ? segment.toLowerCase() === expected.toLowerCase()\n      : segment === expected;\n  });\n}\n\nfunction isUsableExecutable(candidate) {\n  try {\n    const info = fs.statSync(candidate);\n    if (!info.isFile()) return false;\n    fs.accessSync(candidate, fs.constants.R_OK);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nfunction buildInvocation(executable, args) {\n  if (!isCanonicalItoEntry(executable)) {\n    throw new Error(\n      `Refusing to invoke an Itô CLI shim. Set ${EXECUTABLE_OVERRIDE} to the absolute dist/bin/ito.js path.`\n    );\n  }\n  return Object.freeze({\n    executable: process.execPath,\n    args: Object.freeze([executable, ...args]),\n  });\n}\n\nfunction invokeIto(executable, args, environment = process.env) {\n  const invocation = buildInvocation(executable, args);\n  const command = getInvocationCommand(args);\n  const isNodeQualification = command === \"evals\";\n  const isDeviceLogin = command === \"login\";\n  const result = spawnSync(invocation.executable, invocation.args, {\n    cwd: process.cwd(),\n    encoding: \"utf8\",\n    // Keep policy helpers immutable for callers, but give child-process","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/ito.js#L239-L275","documentation":"Thrown by buildInvocation at scripts/ito.js:255-260 when the executable passed in does not satisfy isCanonicalItoEntry. This is a defense-in-depth re-check: resolveItoExecutable already validated the executable via assertUsableExecutable, so under normal main() flow this is unreachable. It exists so that any caller importing buildInvocation directly (the module exports it at ito.js:322) cannot bypass the canonical-entry requirement. The error text names ECC_ITO_CLI_EXECUTABLE explicitly because that is the only sanctioned route to a credential-bearing binary.","triggerScenarios":"Calling buildInvocation(executable, args) directly from a test or downstream tool with an executable path whose trailing segments are not [cli, ito-compute-cli, dist, bin, ito.js]. Not reachable from the CLI's main() under correct control flow because resolveItoExecutable already enforced the same invariant.","commonSituations":"A downstream script imports { buildInvocation } from scripts/ito.js and passes a shim, wrapper, or renamed entry. Effectively impossible to hit through `ecc ito` itself unless resolveItoExecutable or assertUsableExecutable is later refactored to return a non-canonical path.","solutions":["Do not pass a shim or wrapper to buildInvocation — pass the canonical dist/bin/ito.js path returned by resolveItoExecutable.","If you are calling from downstream code, obtain the executable via resolveItoExecutable(environment) rather than constructing it yourself.","If genuinely needing to invoke a non-canonical entry, that is explicitly unsupported; the canonical CLI is unpublished for security reasons."],"exampleFix":"// before (downstream caller)\nconst { buildInvocation } = require('./scripts/ito.js');\nconst inv = buildInvocation('/usr/local/bin/ito-shim', ['status']);\n// after\nconst { resolveItoExecutable, buildInvocation } = require('./scripts/ito.js');\nconst exe = resolveItoExecutable(process.env);   // honors ECC_ITO_CLI_EXECUTABLE\nconst inv = buildInvocation(exe, ['status']);","handlingStrategy":"validation","validationCode":"const { resolveItoExecutable } = require('./scripts/ito.js');\n// Downstream callers: never construct the executable path yourself.\nconst exe = resolveItoExecutable(process.env);\nconst invocation = buildInvocation(exe, args);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat resolveItoExecutable as the single source of truth for the executable path.","Do not import buildInvocation in downstream code without also importing resolveItoExecutable.","Add a unit test that buildInvocation throws on a non-canonical path so regressions are caught."],"tags":["cli","ito","security","api","defense-in-depth"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}