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
- Strip or reject NUL bytes from the input before calling execute, e.g. value.replace(/\0/g, '').
- Pass binary data via the stdin file input instead of embedding it in command/args.
- 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
- Send binary payloads via stdin files, never as arguments
- Sanitize any input derived from binary or null-separated data
- Reject NUL at your own API boundary before calling execute
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
- ACPX provider package name is invalid
- Could not verify the remote ACPX runner platform.
- External chat text exceeds its processing limit
- github_webhook_recovery_invalid_input
- HEIF file type is missing
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)