{"record":{"id":"e3d60d0b78db4333","repo":"mastra-ai/mastra","slug":"worker-label-must-stay-within-the-deployed-arti","errorCode":null,"errorMessage":"Worker ${label} must stay within the deployed artifact root.","messagePattern":"Worker (.+?) must stay within the deployed artifact root\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"deployers/sandbox/src/worker.ts","lineNumber":206,"sourceCode":"    for (const name of Object.keys(resourceLimits)) {\n      if (!knownLimits.has(name)) throw new Error(`Unknown worker resource limit: ${name}.`);\n    }\n    for (const [name, value] of [\n      ['cpuTimeSeconds', resourceLimits.cpuTimeSeconds],\n      ['addressSpaceBytes', resourceLimits.addressSpaceBytes],\n      ['fileSizeBytes', resourceLimits.fileSizeBytes],\n      ['openFiles', resourceLimits.openFiles],\n    ] as const) {\n      if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {\n        throw new Error(`Worker resourceLimits.${name} must be a positive safe integer.`);\n      }\n    }\n  }\n}\n\nfunction validateRelativePath(value: string, label: string): void {\n  if (!value || posix.isAbsolute(value) || posix.normalize(value).startsWith('..')) {\n    throw new Error(`Worker ${label} must stay within the deployed artifact root.`);\n  }\n}\n\nfunction validateInput(input: SandboxWorkerInput | undefined): void {\n  if (input?.type === 'file') validateRelativePath(input.path, 'input file path');\n}\n\nfunction normalizeResourceLimits(\n  limits: SandboxWorkerResourceLimits | undefined,\n): NormalizedResourceLimits | undefined {\n  if (!limits || Object.values(limits).every(value => value === undefined)) return undefined;\n  return {\n    cpuTimeSeconds: limits.cpuTimeSeconds,\n    addressSpaceBytes: limits.addressSpaceBytes,\n    addressSpaceKilobytes:\n      limits.addressSpaceBytes === undefined ? undefined : Math.floor(limits.addressSpaceBytes / 1024),\n    fileSizeBytes: limits.fileSizeBytes,\n    fileSizeBlocks: limits.fileSizeBytes === undefined ? undefined : Math.floor(limits.fileSizeBytes / 512),","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/deployers/sandbox/src/worker.ts#L188-L224","documentation":"validateRelativePath requires a path used inside the deployed worker artifact to be non-empty, relative, and not escape the artifact root after normalization. It guards workingDirectory and file-type worker input paths so uploads and cd targets can never resolve outside the deployed directory (path traversal defense).","triggerScenarios":"Passing deployWorkerToSandbox options.workingDirectory = '/app' (absolute), '' (empty), or '../shared'; or passing input: { type: 'file', path: '../../etc/passwd' } (also via deployment.relaunch({ input }) which re-validates). Any path whose posix.normalize starts with '..' triggers it.","commonSituations":"Using an absolute host path copied from local machine config; building paths with string concatenation where a parent dir slips in ('..' segments); defaulting to '' when a config key is missing; trying to mount or read shared files outside the artifact root; Windows-style absolute paths like 'C:\\data' after normalization still count as relative but leading-slash POSIX paths do not.","solutions":["Use a relative path such as '.', 'dist', or 'bin/server.js' that resolves inside the artifact you deploy in dir.","Strip leading slashes and resolve '..' segments against your intended base before calling, or use posix.resolve(base, p) and verify the result starts with the base.","For data living outside the artifact, stage it as stdin input (input: { type: 'stdin', data }) instead of a file path.","For relaunch input, ensure the file path is relative to the original remoteDir, not the host filesystem."],"exampleFix":"// before\nawait deployWorkerToSandbox({ sandbox, dir: './worker', command: 'node', workingDirectory: '/opt/worker/dist' });\nawait deployWorkerToSandbox({ sandbox, dir: './worker', command: 'node', input: { type: 'file', path: '../payload.json' } });\n// after\nawait deployWorkerToSandbox({ sandbox, dir: './worker', command: 'node', workingDirectory: 'dist' });\nawait deployWorkerToSandbox({ sandbox, dir: './worker', command: 'node', input: { type: 'file', path: 'payload.json' } });","handlingStrategy":"validation","validationCode":"import { posix } from 'node:path';\nfunction assertSafeRelativePath(value, label) {\n  if (!value || posix.isAbsolute(value) || posix.normalize(value).startsWith('..')) {\n    throw new Error(`${label} must be a relative path inside the artifact root, got: ${value}`);\n  }\n}\nassertSafeRelativePath(options.workingDirectory ?? '.', 'workingDirectory');\nif (options.input?.type === 'file') assertSafeRelativePath(options.input.path, 'input path');","typeGuard":"function isSafeRelativePath(value) {\n  return typeof value === 'string' && value.length > 0 &&\n    !posix.isAbsolute(value) && !posix.normalize(value).startsWith('..');\n}","tryCatchPattern":"try {\n  await deployWorkerToSandbox(options);\n} catch (error) {\n  if (error instanceof Error && error.message.includes('must stay within the deployed artifact root')) {\n    console.error(`Make ${error.message.match(/Worker (.+) must/)?.[1]} a relative path like 'dist' or 'data/input.json'`);\n  } else throw error;\n}","preventionTips":["Always join user-supplied segments with posix.resolve(base, p) and assert the result starts with base before passing.","Never copy absolute host paths into workingDirectory or input file paths.","Sanitize config-sourced paths by stripping leading '/' and rejecting '..' segments early in your config loader.","Use stdin input instead of file paths for data generated outside the deployed artifact."],"tags":["validation","path-traversal","security","worker"],"backgroundTag":"path-escape-rejected","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}