{"record":{"id":"31fa0538093f9046","repo":"microsoft/aspire","slug":"the-path-must-not-contain-segments","errorCode":null,"errorMessage":"The path must not contain \"..\" segments.","messagePattern":"The path must not contain \"\\.\\.\" segments\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs","lineNumber":3252,"sourceCode":"        {\n            normalizedPath = normalizedPath[2..];\n        }\n\n        if (normalizedPath.StartsWith('/'))\n        {\n            throw new ArgumentException(\"The path must be a relative path.\", nameof(path));\n        }\n\n        // Reject path traversal segments. These are virtual Docker container paths (not host\n        // filesystem paths), so Path.GetFullPath cannot be used — it produces platform-specific\n        // results (e.g. D:\\app\\dist on Windows). Segment-based validation works correctly\n        // cross-platform for container paths.\n        var segments = normalizedPath.Split('/', StringSplitOptions.RemoveEmptyEntries);\n        foreach (var segment in segments)\n        {\n            if (segment == \"..\")\n            {\n                throw new ArgumentException(\"The path must not contain \\\"..\\\" segments.\", nameof(path));\n            }\n        }\n\n        return string.Join('/', segments);\n    }\n\n    /// <summary>\n    /// Resolves the Node.js version to use for a project by checking common configuration files.\n    /// </summary>\n    /// <param name=\"workingDirectory\">The working directory of the Node.js project.</param>\n    /// <param name=\"logger\">The logger for diagnostic messages.</param>\n    /// <returns>The resolved Node.js major version number as a string.</returns>\n    private static string ResolveNodeVersion(string workingDirectory, ILogger logger)\n    {\n        // Follow the same shape as Cloud Native Buildpacks-style tooling for Node selection:\n        // pinned toolchain files (.nvmrc, .node-version, .tool-versions) are treated as\n        // authoritative runtime intent, while package.json engines.node is compatibility\n        // metadata rather than a deployment image pin. If there is no explicit toolchain pin,","sourceCodeStart":3234,"sourceCodeEnd":3270,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs#L3234-L3270","documentation":"After rejecting absolute paths, the same validator splits the path on '/' and rejects any '..' segment. These are virtual Docker container paths, so Path.GetFullPath can't normalize them portably; '..' segments could escape the intended container directory and are therefore blocked outright with an ArgumentException.","triggerScenarios":"Passing paths containing '..' such as \"../shared\", \"dist/../../out\", or paths where normalization would produce '..' (e.g. \"a/../b\" segments surviving split validation).","commonSituations":"Attempting to reference a sibling project directory from a container path; copy-pasted relative paths with traversal; trying to write output outside the app directory in the generated Dockerfile.","solutions":["Remove '..' segments and pass a path rooted inside the app directory (e.g. \"dist\", \"out/app\").","Copy shared artifacts into the app directory instead of traversing to them.","Normalize the path yourself before calling, ensuring no segment equals \"..\"."],"exampleFix":"// before\noptions.OutputPath = \"../shared/dist\";\n// after\noptions.OutputPath = \"dist\";","handlingStrategy":"validation","validationCode":"static bool HasNoTraversal(string? path) =>\n    !string.IsNullOrEmpty(path) && path.Split('/', StringSplitOptions.RemoveEmptyEntries).All(s => s != \"..\");","typeGuard":"bool HasNoTraversal(string? path) => !string.IsNullOrEmpty(path) && path.Split('/', StringSplitOptions.RemoveEmptyEntries).All(s => s != \"..\");","tryCatchPattern":"try { options.OutputPath = p; } catch (ArgumentException ex) when (ex.Message.Contains(\"..\\\" segments\")) { /* collapse or rewrite the path */ }","preventionTips":["Resolve '..' before handing paths to Dockerfile generation APIs.","Copy needed files into the app directory instead of traversing out of it.","Lint configuration for '..' segments in path options."],"tags":["javascript","nextjs","docker","path-traversal"],"backgroundTag":"path-traversal-blocked","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}