{"record":{"id":"517b44a0722fb746","repo":"hashicorp/nomad","slug":"failed-to-sandbox-alloc-dir-q-w","errorCode":null,"errorMessage":"failed to sandbox alloc dir %q: %w","messagePattern":"failed to sandbox alloc dir %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/template/renderer/z_template_render.go","lineNumber":84,"sourceCode":"\t\t\tos.Exit(ExitError)\n\t\t}\n\t}\n}\n\nfunc readTemplate() error {\n\tvar (\n\t\tsandboxPath, sourcePath string\n\t\terr                     error\n\t)\n\n\tflags := flag.NewFlagSet(\"template-render\", flag.ExitOnError)\n\tflags.StringVar(&sandboxPath, \"sandbox-path\", \"\", \"\")\n\tflags.StringVar(&sourcePath, \"source-path\", \"\", \"\")\n\tflags.Parse(os.Args[3:])\n\n\tsourcePath, err = sandbox(sandboxPath, sourcePath) // platform-specific sandboxing\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to sandbox alloc dir %q: %w\", sandboxPath, err)\n\t}\n\n\tf, err := os.Open(sourcePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open source file %q: %w\", sourcePath, err)\n\t}\n\tdefer f.Close()\n\n\t_, err = io.Copy(os.Stdout, f)\n\treturn err\n}\n\nfunc writeTemplate() (*renderer.RenderResult, error) {\n\n\tvar (\n\t\tsandboxPath, destPath, perms, user, group string\n\t)\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/template/renderer/z_template_render.go#L66-L102","documentation":"The template render subprocess (z_template_render.go init/readTemplate) invokes the platform-specific sandbox() before opening the template source file; when sandbox() fails (e.g. the chroot-relative destination error above), this wrapper reports that the alloc dir could not be sandboxed. It means the renderer could not securely map the source path into the alloc-dir sandbox, so it aborts rather than reading an unsandboxed path.","triggerScenarios":"readTemplate is called during subprocess init; it parses -sandbox-path and -source-path flags and calls sandbox(sandboxPath, sourcePath). Any error returned by sandbox (such as filepath.Rel failure when the source path isn't under the sandbox path) is wrapped with this message and returned, aborting the render.","commonSituations":"Consul Template render events where the source/destination paths don't sit inside the alloc dir; clients where chroot behaves differently than expected and path mapping fails; alloc dirs with symlinks or unusual mount points breaking path relativization; upgrades changing template sandbox behavior causing previously working templates to fail.","solutions":["Inspect the wrapped inner error (often 'could not find destination path relative to chroot') and align template source/destination paths within the alloc dir","Rewrite template block source/destination to use alloc-dir-relative paths (local/, secrets/)","Check client alloc_dir configuration for symlinks or non-standard mounts and normalize them","Review Nomad version changelog for template sandbox behavior changes and adjust the job spec accordingly","Restart the allocation after fixing paths so the renderer subprocess re-runs with correct flags"],"exampleFix":"// before: template source outside alloc dir sandbox\ntemplate {\n  source      = \"/opt/templates/app.conf.tpl\"\n  destination = \"local/app.conf\"\n}\n\n// after: source staged inside the alloc dir (or inlined via data)\ntemplate {\n  data        = file(\"templates/app.conf.tpl\") // or embed the template text\n  destination = \"local/app.conf\"\n}","handlingStrategy":"validation","validationCode":"// Pre-check that template paths live under the sandbox/alloc dir before render\nfunc pathUnderSandbox(sandboxPath, p string) error {\n    absSandbox, err := filepath.Abs(sandboxPath)\n    if err != nil { return err }\n    absP, err := filepath.Abs(p)\n    if err != nil { return err }\n    rel, err := filepath.Rel(absSandbox, absP)\n    if err != nil || strings.HasPrefix(rel, \"..\") {\n        return fmt.Errorf(\"path %q is not under sandbox %q\", p, sandboxPath)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep both template source and destination inside the alloc dir","Avoid symlinks or unusual mounts under the client alloc_dir","Pin template sandbox behavior expectations when upgrading Nomad; test renders in staging","Log and alert on render subprocess failures so path misconfigurations surface early"],"tags":["nomad","template","renderer","sandbox","allocdir"],"backgroundTag":"path-escape-sandbox","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}