usebruno/bruno · error · Error

Invalid scutil --proxy output

Error message

Invalid scutil --proxy output

What it means

parseScutilOutput guards against a non-string argument before processing. Because execFileAsync returns a Buffer/string, this is a defensive invariant check; if reached it means the caller passed invalid data into the parser directly.

Source

Thrown at packages/bruno-requests/src/network/system-proxy/utils/macos.ts:23

export class MacOSProxyResolver implements ProxyResolver {
  async detect(opts?: { timeoutMs?: number }): Promise<ProxyConfiguration> {
    const timeoutMs = opts?.timeoutMs ?? 10000;
    const execOpts: ExecFileOptions = {
      timeout: timeoutMs,
      maxBuffer: 1024 * 1024
    };

    try {
      const { stdout } = await execFileAsync('scutil', ['--proxy'], execOpts);
      return this.parseScutilOutput(stdout);
    } catch (error) {
      throw new Error(`macOS proxy detection failed: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  private parseScutilOutput(output: string): ProxyConfiguration {
    if (typeof output !== 'string') {
      throw new Error('Invalid scutil --proxy output');
    }

    const cleanLines = output.split('\n')
      .map((line) => line.trim())
      .filter((line) => line.length > 0);

    const dictStart = cleanLines.findIndex((line) => line.includes('<dictionary>'));
    if (dictStart === -1) {
      throw new Error('Invalid scutil --proxy output format');
    }
    const config = this.parseConfiguration(cleanLines, dictStart);
    return this.buildProxyConfiguration(config);
  }

  private parseConfiguration(lines: string[], startIndex: number): Record<string, any> {
    const config: Record<string, any> = {};
    let i = startIndex + 1;

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Ensure any caller passes the string stdout from execFileAsync (call .toString() on Buffers).
  2. In tests, pass valid string fixtures instead of objects.

Example fix

// before
resolver.parseScutilOutput(bufferFromScutil); // Buffer, not string -> throws

// after
resolver.parseScutilOutput(bufferFromScutil.toString('utf8'));
Defensive patterns

Strategy: type-guard

Validate before calling

function ensureString(stdout): string { if (typeof stdout !== 'string') throw new TypeError('scutil output must be a string'); return stdout; }

Type guard

function isString(v): v is string { return typeof v === 'string'; }

Prevention

When it happens

Trigger: parseScutilOutput invoked with null, undefined, a number, or a Buffer that was not decoded to a string.

Common situations: Effectively unreachable through the normal detect() path; only reachable via direct unit-test invocation with bad input or a future refactor that drops the toString conversion.

Related errors


AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13). Data as JSON: /api/errors/c8341a1ba232c9c7. Report an issue: GitHub.