paperclipai/paperclip · error

Sandbox command values cannot contain NUL.

Error message

Sandbox command values cannot contain NUL.

What it means

shellQuote wraps every command/env value in POSIX single quotes for execution inside the CreateOS sandbox, and rejects any value containing a NUL byte. NUL cannot appear in shell arguments or C strings, so allowing it would produce a silently truncated or corrupted remote command.

Solutions

  1. Strip or reject NUL bytes from the input before calling execute, e.g. value.replace(/\0/g, '').
  2. Pass binary data via the stdin file input instead of embedding it in command/args.
  3. Decode binary sources with explicit null-byte-safe handling (e.g. split on '\0' and pass elements separately).

Example fix

// before
exec({ command: "echo", args: [rawList] }) // rawList contains \0
// after
exec({ command: "echo", args: [rawList.replace(/\0/g, " ")] })
Defensive patterns

Strategy: validation

Validate before calling

function assertNoNul(values) {
  for (const v of values) if (typeof v === 'string' && v.includes('\0')) throw new Error('NUL byte in sandbox command input');
}
assertNoNul([command, ...args, cwd, ...Object.values(env ?? {})]);

Prevention

When it happens

Trigger: Calling the plugin's execute path with params.command, an args element, an env key/value, or cwd containing a '\0' character — e.g. binary data read as a UTF-8/latin1 string or a value built with String.fromCharCode(0).

Common situations: Piping binary file contents into a command argument instead of stdin; reading a null-separated list (find -print0 / xargs -0 style) and passing the raw string as one arg; corrupted input decoded with the wrong encoding.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/4f90acd1baeec473. Report an issue: GitHub.

Appendix: source

Thrown at packages/plugins/sandbox-providers/createos/src/execute.ts:13

import { randomUUID } from "node:crypto";
import { StringDecoder } from "node:string_decoder";
import { setTimeout as delay } from "node:timers/promises";
import type { PluginEnvironmentExecuteParams, PluginEnvironmentExecuteResult } from "@paperclipai/plugin-sdk";
import { CreateosApiError, CreateosClient, identifier, object } from "./client.js";

const MAX_LINE_BYTES = 1_048_576;
const MAX_CAPTURE_CHARS = 4_194_304;

export class CreateosCleanupError extends Error {}

export function shellQuote(value: string): string {
  if (value.includes("\0")) throw new Error("Sandbox command values cannot contain NUL.");
  return `'${value.replace(/'/g, `'"'"'`)}'`;
}

function commandScript(params: PluginEnvironmentExecuteParams, stdinPath: string | null): string {
  if (!params.command) throw new Error("A sandbox command is required.");
  const env = Object.entries(params.env ?? {}).map(([key, value]) => {
    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) || typeof value !== "string") {
      throw new Error("Invalid sandbox environment variable.");
    }
    return `${key}=${shellQuote(value)}`;
  });
  const command = [params.command, ...(params.args ?? [])].map(shellQuote).join(" ");
  return [
    params.cwd ? `cd -- ${shellQuote(params.cwd)} || exit` : "",
    `exec env ${env.join(" ")} ${command}${stdinPath ? ` < ${shellQuote(stdinPath)}` : ""}`,
  ].filter(Boolean).join("\n");
}

View on GitHub (pinned to 3f1d897a7c)