affaan-m/ECC · error · Error

Executable must be a non-empty argv entry without control by

Error message

Executable must be a non-empty argv entry without control bytes.

What it means

validateExecutable rejects an empty executable or one containing NUL (\0), CR (\r), or LF (\n) control bytes. These would break argv handling or enable line-splitting injection. This is the first executable check, run before the shell-command-string detection at lines 62-71.

Source

Thrown at skills/terminal-opener/scripts/open-terminal.js:53

function isAbsolutePath(value) {
  return path.isAbsolute(value) || path.win32.isAbsolute(value);
}

function validateTerminalName(value) {
  if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(value)) {
    throw new Error('Invalid terminal name; use a simple adapter name such as wezterm.');
  }
}

function validateCwd(value) {
  if (value.includes('\0')) throw new Error('--cwd must not contain a NUL byte.');
  if (!isAbsolutePath(value)) throw new Error('--cwd must be an absolute path.');
}

function validateExecutable(value) {
  if (!value || /[\0\r\n]/.test(value)) {
    throw new Error('Executable must be a non-empty argv entry without control bytes.');
  }

  const whitespaceIndex = value.search(/\s/);
  const separatorIndexes = [value.indexOf('/'), value.indexOf('\\')].filter(index => index >= 0);
  const firstSeparatorIndex = separatorIndexes.length > 0 ? Math.min(...separatorIndexes) : -1;
  const resemblesExecutablePath = isAbsolutePath(value)
    || (firstSeparatorIndex >= 0 && (whitespaceIndex < 0 || firstSeparatorIndex < whitespaceIndex));

  if (whitespaceIndex >= 0 && !resemblesExecutablePath) {
    throw new Error(
      'Executable must be one argv entry, not an interpolated shell command string.'
    );
  }
  if (!resemblesExecutablePath && /[;&|<>`$]/.test(value)) {
    throw new Error(
      'Executable must be one argv entry, not an interpolated shell command string.'
    );
  }

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Provide a non-empty executable token after -- with no control bytes.
  2. If the executable comes from a template, sanitize it: strip \0, \r, \n.
  3. Double-check the token order: executable first, then its arguments.

Example fix

// before
parseArgs(['--', '', 'arg']); // empty executable

// after
parseArgs(['--', '/bin/echo', 'arg']);
Defensive patterns

Strategy: validation

Validate before calling

function safeExecutable(value) {
  if (!value || /[\0\r\n]/.test(value)) {
    throw new Error('Executable must be non-empty with no control bytes');
  }
  return value;
}

Prevention

When it happens

Trigger: options.executable is '' (e.g. '--' immediately followed by another '--' or end of args producing an empty token) or contains \0/\r/\n. validateExecutable is called from parseArgs when an executable is present.

Common situations: Passing an empty executable; a template literal that introduced a newline into the executable name; binary/corrupted argv; accidentally putting a flag where the executable goes.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/4388a6a5809a020e. Report an issue: GitHub.