{"record":{"id":"76cd94cfb6a467a0","repo":"projectdiscovery/nuclei","slug":"normalize-output-file-q-w","errorCode":null,"errorMessage":"normalize output file %q: %w","messagePattern":"normalize output file %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/libs/krbforge/krbforge.go","lineNumber":216,"sourceCode":"\t}, nil\n}\n\nfunc normalizeOutputFile(executionID string, outputFile string) (string, error) {\n\tif outputFile == \"\" || outputFile == \"-\" {\n\t\treturn outputFile, nil\n\t}\n\n\tif protocolstate.IsLfaAllowed(&types.Options{ExecutionId: executionID}) {\n\t\t// Preserve the existing relative-path behavior when\n\t\t// -allow-local-file-access is enabled: avoid implicit CWD writes by\n\t\t// placing relative ccache paths in temp.\n\t\tif !filepath.IsAbs(outputFile) {\n\t\t\toutputFile = filepath.Join(os.TempDir(), outputFile)\n\t\t}\n\n\t\tnormalized, err := filepath.Abs(outputFile)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"normalize output file %q: %w\", outputFile, err)\n\t\t}\n\n\t\treturn normalized, nil\n\t}\n\n\tnormalized := outputFile\n\tif !filepath.IsAbs(normalized) {\n\t\tnormalized = filepath.Join(config.DefaultConfig.GetTemplateDir(), normalized)\n\t}\n\n\tnormalized, err := filepath.Abs(normalized)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"normalize output file %q: %w\", outputFile, err)\n\t}\n\n\tif filepathutil.IsPathWithinDirectory(normalized, config.DefaultConfig.GetTemplateDir()) {\n\t\treturn normalized, nil\n\t}","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/krbforge/krbforge.go#L198-L234","documentation":"With -allow-local-file-access enabled, normalizeOutputFile places relative output paths under the OS temp dir and then calls filepath.Abs; this error wraps an Abs failure on that branch. filepath.Abs almost never fails on Linux (its main failure is a deleted working directory or an invalid path); on Windows, overlong paths or illegal characters can trigger it.","triggerScenarios":"The process working directory was removed while the template ran; the output_file string contains NUL bytes, control characters, or exceeds platform path limits; exotic filesystem states making absolute-path resolution fail.","commonSituations":"Templates that delete or move their own CWD before forging a ticket; unvalidated user input flowing into the outputFile argument of CreateSilverTicket; Windows path-length limits (260 chars) with deep temp-dir nesting.","solutions":["Pass an absolute output path so Abs has nothing fragile to resolve","Sanitize the filename: strip NUL and control characters, keep the full path within OS limits","If the template removed its working directory, write to an absolute temp path instead"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function safeOutputPath(p) {\n  if (p === '-' || !p) return p;\n  if (/[\\x00-\\x1f]/.test(p)) throw new Error('output path contains control characters');\n  if (p.length > 200) throw new Error('output path too long');\n  return p;\n}\nsafeOutputPath(outputFile);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass absolute output paths when -allow-local-file-access is enabled","Sanitize user-controlled filenames before they reach CreateSilverTicket","Do not delete or move the process working directory while a template runs"],"tags":["kerberos","krbforge","filesystem","path"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}