{"record":{"id":"91fe5312137443a3","repo":"paperclipai/paperclip","slug":"remote-codex-working-directory-must-be-a-normalize","errorCode":null,"errorMessage":"Remote Codex working directory must be a normalized absolute path","messagePattern":"Remote Codex working directory must be a normalized absolute path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/codex/codex-boundaries.ts","lineNumber":129,"sourceCode":"    ) {\n      throw new Error(\n        \"Codex working directory is outside the assigned workspace\",\n      );\n    }\n  }\n  return resolved;\n}\n\nfunction validateRemoteRunnerWorkingDirectory(\n  workingDirectory: string,\n  environment: NodeJS.ProcessEnv,\n): string {\n  if (\n    !posix.isAbsolute(workingDirectory) ||\n    posix.normalize(workingDirectory) !== workingDirectory ||\n    /[\\u0000-\\u001f\\u007f]/u.test(workingDirectory)\n  ) {\n    throw new Error(\n      \"Remote Codex working directory must be a normalized absolute path\",\n    );\n  }\n  if (workingDirectory === posix.parse(workingDirectory).root) {\n    throw new Error(\"Codex working directory cannot be a filesystem root\");\n  }\n  const configuredRoot = environment.PAPERCLIP_WORKSPACE_CWD?.trim();\n  if (!configuredRoot) {\n    throw new Error(\n      \"Remote Codex working directory requires an assigned workspace\",\n    );\n  }\n  if (\n    !posix.isAbsolute(configuredRoot) ||\n    posix.normalize(configuredRoot) !== configuredRoot\n  ) {\n    throw new Error(\n      \"Assigned remote workspace must be a normalized absolute path\",","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/codex/codex-boundaries.ts#L111-L147","documentation":"When the working-directory authority is `remote_runner`, the path is interpreted on a remote host, so local path resolution is not used. Instead the validator requires a POSIX absolute, normalized path (no `..` segments, no trailing or doubled slashes) with no control characters, guaranteeing the remote runner receives an unambiguous location.","triggerScenarios":"Calling `validateCodexWorkingDirectory` with `authority: \"remote_runner\"` and a relative path (\"workspaces/foo\"), a non-normalized path (\"/workspaces/../foo\", \"/workspaces//foo\", \"/workspaces/foo/\"), or a path containing control characters like a newline.","commonSituations":"Passing a Windows-style or local absolute path to a remote runner; concatenating paths without normalization; user input carrying a trailing newline from a form or env var.","solutions":["Send a posix-normalized absolute path: posix.normalize(posix.join(...)) and verify posix.isAbsolute","Strip control characters/whitespace from the path at the source","For remote runners, build paths with path.posix (not the local path module)"],"exampleFix":"// before\nvalidateCodexWorkingDirectory(\"/workspaces/\" + id + \"/\", env, \"remote_runner\");\n// after\nimport { posix } from \"node:path\";\nconst p = posix.normalize(`/workspaces/${id}`);\nvalidateCodexWorkingDirectory(p, env, \"remote_runner\");","handlingStrategy":"validation","validationCode":"import { posix } from \"node:path\";\nfunction validRemoteCwd(p: string): boolean {\n  return posix.isAbsolute(p) && posix.normalize(p) === p && !/[\\u0000-\\u001f\\u007f]/u.test(p) && p !== posix.parse(p).root;\n}\nif (!validRemoteCwd(cwd)) throw new Error(\"remote cwd must be a normalized absolute POSIX path\");","typeGuard":"function isNormalizedAbsolutePosixPath(v: unknown): v is string {\n  return typeof v === \"string\" && posix.isAbsolute(v) && posix.normalize(v) === v && !/[\\u0000-\\u001f\\u007f]/u.test(v);\n}","tryCatchPattern":"try {\n  validateCodexWorkingDirectory(cwd, env, \"remote_runner\");\n} catch (err) {\n  if (err.message.includes(\"must be a normalized absolute path\")) {\n    throw new ConfigError(`remote cwd \"${cwd}\" is relative or non-normalized; build paths with path.posix`);\n  }\n  throw err;\n}","preventionTips":["Always build remote paths with node:path posix helpers, never the platform path module","Trim/sanitize user-supplied path fragments (strip newlines, trailing slashes)","Add a unit test asserting remote cwd candidates survive posix.normalize unchanged"],"tags":["validation","path-format","remote"],"backgroundTag":"invalid-argument-format","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}