{"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":"exception","errorClass":"Error","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/06c5e118c4d3e6c3b7f9445f973a2194c82de193/scripts/ito.js#L239-L275","documentation":"buildInvocation re-runs isCanonicalItoEntry on the executable before constructing the spawn, as a defense-in-depth check: ECC invokes the CLI as `process.execPath <executable> ...args` and refuses to pass a non-canonical entry (for example an `ito` shim resolved from PATH) any arguments, because arguments may carry credentials. In normal flow this is unreachable — resolveItoExecutable already returns a verified canonical path — so hitting it means invokeIto/buildInvocation was called directly with an arbitrary executable string.","triggerScenarios":"Another script imports scripts/ito.js internals and calls invokeIto('/usr/local/bin/ito', args) or buildInvocation with a PATH-resolved shim instead of the resolveItoExecutable() return value.","commonSituations":"Embedding the ECC ito wrapper as a library; refactors that bypass resolveItoExecutable; tests stubbing the executable path with a mock file.","solutions":["Always derive the executable from resolveItoExecutable(environment) and pass that exact value through to invokeIto.","Set ECC_ITO_CLI_EXECUTABLE to the canonical dist/bin/ito.js path so resolution succeeds normally.","In tests, create a fake path whose final segments are dist/bin/ito.js so isCanonicalItoEntry passes."],"exampleFix":"// before\nimport { invokeIto } from '../scripts/ito.js';\ninvokeIto('/usr/local/bin/ito', ['status']); // shim -> throws\n\n// after\nimport { invokeIto, resolveItoExecutable } from '../scripts/ito.js';\ninvokeIto(resolveItoExecutable(process.env), ['status']);","handlingStrategy":"validation","validationCode":"// Never hand-pick an executable string; always flow the resolved value through.\nimport { resolveItoExecutable, invokeIto } from './ito.js';\nconst exe = resolveItoExecutable(process.env); // already passes all checks\ninvokeIto(exe, ['status']); // buildInvocation's re-check now succeeds","typeGuard":null,"tryCatchPattern":"try { invokeIto(exe, args); } catch (e) {\n  if (/Refusing to invoke an Itô CLI shim/.test(e.message)) { throw new Error('Caller bug: executable must come from resolveItoExecutable()'); }\n  throw e;\n}","preventionTips":["Treat resolveItoExecutable() as the single source of truth for the executable; do not re-resolve via PATH or which.","In tests, fake executables whose path ends with cli/ito-compute-cli/dist/bin/ito.js so the canonical check passes."],"tags":["cli","security","ito","internal-api"],"backgroundTag":"invalid-config-path","analyzedSha":"06c5e118c4d3e6c3b7f9445f973a2194c82de193","analyzedAt":"2026-08-18T11:27:13.915Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}