OrchardCMS/OrchardCore · error · FileStoreException

The path ' ' resolves to a physical path outside the file…

Error message

The path '{path}' resolves to a physical path outside the file system store root.

What it means

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.

Solutions

  1. Sanitize the input: strip or reject '..' segments, leading slashes, drive letters, and invalid characters before calling the API.
  2. Use Path.GetFileName / combine the path from trusted components instead of raw user input.
  3. Ensure the store root (the path given to FileSystemStore) is absolute and canonical so the prefix check compares like with like.
  4. If this is a security probe, treat it as suspicious input and reject the request rather than retrying.

Example fix

// before
var path = userSuppliedName; // could be "../../evil.txt"
await fileStore.CreateFileFromStreamAsync(path, stream);
// after
var safeName = Path.GetFileName(userSuppliedName.Replace('\\', '/'));
if (string.IsNullOrWhiteSpace(safeName) || safeName.Contains(".."))
{
    throw new ArgumentException("Invalid file name.", nameof(userSuppliedName));
}
await fileStore.CreateFileFromStreamAsync(safeName, stream);
Defensive patterns

Strategy: validation

Validate before calling

var segments = path.Replace('\\', '/').Split('/', StringSplitOptions.RemoveEmptyEntries);
bool isSafe = segments.Length > 0
    && segments.All(s => s != ".." && s != "." && !Path.IsPathRooted(s) && s.IndexOfAny(Path.GetInvalidFileNameChars()) < 0);

Type guard

static bool IsSafeStorePath(string path) =>
    !string.IsNullOrWhiteSpace(path)
    && !Path.IsPathRooted(path)
    && !path.Split('/', '\\').Any(s => s == "..");

Try / catch

try
{
    await fileStore.GetFileInfoAsync(path);
}
catch (FileStoreException ex) when (ex.Message.Contains("outside the file system store root"))
{
    logger.LogWarning("Rejected path-traversal attempt: {Path}", path);
    return Results.BadRequest("Invalid path.");
}

Prevention

When it happens

Trigger: 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.).

Common situations: 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.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/174f1e0cd77a93c5. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.FileStorage.FileSystem/FileSystemStore.cs:433

    /// <summary>
    /// Translates a relative path in the virtual file store to a physical path in the underlying file system.
    /// </summary>
    /// <param name="path">The relative path within the file store.</param>
    /// <returns></returns>
    /// <remarks>The resulting physical path is verified to be inside designated root file system path.</remarks>
    private string GetPhysicalPath(string path)
    {
        try
        {
            path = this.NormalizePath(path);

            var physicalPath = string.IsNullOrEmpty(path) ? _fileSystemPath : Path.Combine(_fileSystemPath, path);

            // Verify that the resulting path is inside the root file system path.
            var pathIsAllowed = Path.GetFullPath(physicalPath).StartsWith(_fileSystemPath, StringComparison.OrdinalIgnoreCase);
            if (!pathIsAllowed)
            {
                throw new FileStoreException($"The path '{path}' resolves to a physical path outside the file system store root.");
            }

            return physicalPath;
        }
        catch (FileStoreException)
        {
            throw;
        }
        catch (Exception ex)
        {
            throw new FileStoreException($"Cannot resolve physical path with the path '{path}'.", ex);
        }
    }
}

View on GitHub (pinned to 4306c0717f)