{"record":{"id":"174f1e0cd77a93c5","repo":"OrchardCMS/OrchardCore","slug":"the-path-path-resolves-to-a-physical-path-outside-the-file","errorCode":null,"errorMessage":"The path '{path}' resolves to a physical path outside the file system store root.","messagePattern":"The path '(.+?)' resolves to a physical path outside the file system store root\\.","errorType":"exception","errorClass":"FileStoreException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.FileStorage.FileSystem/FileSystemStore.cs","lineNumber":433,"sourceCode":"    /// <summary>\n    /// Translates a relative path in the virtual file store to a physical path in the underlying file system.\n    /// </summary>\n    /// <param name=\"path\">The relative path within the file store.</param>\n    /// <returns></returns>\n    /// <remarks>The resulting physical path is verified to be inside designated root file system path.</remarks>\n    private string GetPhysicalPath(string path)\n    {\n        try\n        {\n            path = this.NormalizePath(path);\n\n            var physicalPath = string.IsNullOrEmpty(path) ? _fileSystemPath : Path.Combine(_fileSystemPath, path);\n\n            // Verify that the resulting path is inside the root file system path.\n            var pathIsAllowed = Path.GetFullPath(physicalPath).StartsWith(_fileSystemPath, StringComparison.OrdinalIgnoreCase);\n            if (!pathIsAllowed)\n            {\n                throw new FileStoreException($\"The path '{path}' resolves to a physical path outside the file system store root.\");\n            }\n\n            return physicalPath;\n        }\n        catch (FileStoreException)\n        {\n            throw;\n        }\n        catch (Exception ex)\n        {\n            throw new FileStoreException($\"Cannot resolve physical path with the path '{path}'.\", ex);\n        }\n    }\n}\n","sourceCodeStart":415,"sourceCodeEnd":448,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.FileStorage.FileSystem/FileSystemStore.cs#L415-L448","documentation":"FileSystemStore.GetPhysicalPath validates that combining the store root with the supplied virtual path still resolves inside the store root (a path-traversal guard). If the resolved full path escapes the root, a FileStoreException is thrown. Nearly every read/write/copy/move operation funnels through this method.","triggerScenarios":"Passing a path containing '..' segments (e.g. '../../secret.txt'), an absolute path, or a rooted drive path like 'C:/tmp/x.txt' to any IFileStore method (GetFileInfoAsync, CreateFileFromStreamAsync, CopyFileAsync, MoveFileAsync, etc.).","commonSituations":"User-supplied filenames passed straight into file-store APIs without sanitization; URL-decoded '%2e%2e%2f' segments; comparing paths built with different separators; case where the store root itself is a relative path so the prefix check misfires.","solutions":["Sanitize the input: strip or reject '..' segments, leading slashes, drive letters, and invalid characters before calling the API.","Use Path.GetFileName / combine the path from trusted components instead of raw user input.","Ensure the store root (the path given to FileSystemStore) is absolute and canonical so the prefix check compares like with like.","If this is a security probe, treat it as suspicious input and reject the request rather than retrying."],"exampleFix":"// before\nvar path = userSuppliedName; // could be \"../../evil.txt\"\nawait fileStore.CreateFileFromStreamAsync(path, stream);\n// after\nvar safeName = Path.GetFileName(userSuppliedName.Replace('\\\\', '/'));\nif (string.IsNullOrWhiteSpace(safeName) || safeName.Contains(\"..\"))\n{\n    throw new ArgumentException(\"Invalid file name.\", nameof(userSuppliedName));\n}\nawait fileStore.CreateFileFromStreamAsync(safeName, stream);","handlingStrategy":"validation","validationCode":"var segments = path.Replace('\\\\', '/').Split('/', StringSplitOptions.RemoveEmptyEntries);\nbool isSafe = segments.Length > 0\n    && segments.All(s => s != \"..\" && s != \".\" && !Path.IsPathRooted(s) && s.IndexOfAny(Path.GetInvalidFileNameChars()) < 0);","typeGuard":"static bool IsSafeStorePath(string path) =>\n    !string.IsNullOrWhiteSpace(path)\n    && !Path.IsPathRooted(path)\n    && !path.Split('/', '\\\\').Any(s => s == \"..\");","tryCatchPattern":"try\n{\n    await fileStore.GetFileInfoAsync(path);\n}\ncatch (FileStoreException ex) when (ex.Message.Contains(\"outside the file system store root\"))\n{\n    logger.LogWarning(\"Rejected path-traversal attempt: {Path}\", path);\n    return Results.BadRequest(\"Invalid path.\");\n}","preventionTips":["Never pass raw user input as a store path; reduce it to Path.GetFileName first.","Reject or decode-and-check URL segments before building store paths.","Configure FileSystemStore with an absolute canonical root path.","Treat 'outside the store root' errors as potential security events and log them."],"tags":["path-traversal","security","file-storage"],"backgroundTag":"path-traversal-blocked","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}