{"record":{"id":"4f90acd1baeec473","repo":"paperclipai/paperclip","slug":"sandbox-command-values-cannot-contain-nul","errorCode":null,"errorMessage":"Sandbox command values cannot contain NUL.","messagePattern":"Sandbox command values cannot contain NUL\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/createos/src/execute.ts","lineNumber":13,"sourceCode":"import { randomUUID } from \"node:crypto\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { PluginEnvironmentExecuteParams, PluginEnvironmentExecuteResult } from \"@paperclipai/plugin-sdk\";\nimport { CreateosApiError, CreateosClient, identifier, object } from \"./client.js\";\n\nconst MAX_LINE_BYTES = 1_048_576;\nconst MAX_CAPTURE_CHARS = 4_194_304;\n\nexport class CreateosCleanupError extends Error {}\n\nexport function shellQuote(value: string): string {\n  if (value.includes(\"\\0\")) throw new Error(\"Sandbox command values cannot contain NUL.\");\n  return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\nfunction commandScript(params: PluginEnvironmentExecuteParams, stdinPath: string | null): string {\n  if (!params.command) throw new Error(\"A sandbox command is required.\");\n  const env = Object.entries(params.env ?? {}).map(([key, value]) => {\n    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) || typeof value !== \"string\") {\n      throw new Error(\"Invalid sandbox environment variable.\");\n    }\n    return `${key}=${shellQuote(value)}`;\n  });\n  const command = [params.command, ...(params.args ?? [])].map(shellQuote).join(\" \");\n  return [\n    params.cwd ? `cd -- ${shellQuote(params.cwd)} || exit` : \"\",\n    `exec env ${env.join(\" \")} ${command}${stdinPath ? ` < ${shellQuote(stdinPath)}` : \"\"}`,\n  ].filter(Boolean).join(\"\\n\");\n}\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/plugins/sandbox-providers/createos/src/execute.ts#L1-L31","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)."],"exampleFix":"// before\nexec({ command: \"echo\", args: [rawList] }) // rawList contains \\0\n// after\nexec({ command: \"echo\", args: [rawList.replace(/\\0/g, \" \")] })","handlingStrategy":"validation","validationCode":"function assertNoNul(values) {\n  for (const v of values) if (typeof v === 'string' && v.includes('\\0')) throw new Error('NUL byte in sandbox command input');\n}\nassertNoNul([command, ...args, cwd, ...Object.values(env ?? {})]);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["shell","injection-guard","input-validation","nul-byte"],"backgroundTag":"invalid-argument-value","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}