stride3d/stride · error · InvalidOperationException
Relative path is not allowed in FileSystemProvider.
Error message
Relative path is not allowed in FileSystemProvider.
What it means
OpenStream rejects URLs containing '..' path segments when a local base path is set, because they could escape the provider's root directory. This is a deliberate path-traversal guard, not a file-system error.
Solutions
- Resolve and normalize the URL to an absolute path before passing it to OpenStream
- Sanitize user input: strip or reject '..' segments
- Restructure code so files outside the base are accessed via a different provider, not traversal
Example fix
// before
var stream = provider.OpenStream($"{userInput}", VirtualFileMode.Open, VirtualFileAccess.Read);
// after
var safe = Path.GetFullPath(Path.Combine(basePath, userInput));
if (!safe.StartsWith(basePath)) throw new UnauthorizedAccessException();
var stream = provider.OpenStream(safe, VirtualFileMode.Open, VirtualFileAccess.Read); Defensive patterns
Strategy: validation
Validate before calling
bool isSafe = !url.Split('/', '\\').Contains("..");
if (!isSafe) throw new ArgumentException("Path traversal detected"); Try / catch
try { stream = provider.OpenStream(url, mode, access); }
catch (InvalidOperationException) { throw new UnauthorizedAccessException($"Rejected path: {url}"); } Prevention
- Treat all user-supplied path segments as untrusted
- Resolve URLs to full paths and verify they stay under the base directory
- Add a central sanitize helper for all file URL construction
When it happens
Trigger: Calling OpenStream with a URL like "../secrets.txt" or "assets/../../etc/passwd" (on any separator style), while the provider has a non-null localBasePath.
Common situations: User-supplied filenames being opened directly, URLs joined from untrusted input, or legitimate relative paths that were never resolved to absolute form first.
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
- A file path cannot end with with directory char '\' or '/'…
- Base path must be absolute, got
- Base path must be non-empty (use null for passthrough).
- Build manifest [ ] must exist
- Can't read beyond end of stream.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/4f805b15c16c175f.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.IO/FileSystemProvider.cs:158
end = -1;
return true;
}
/// <inheritdoc/>
public override string[] ListFiles(string url, string searchPattern, VirtualSearchOption searchOption)
{
return Directory.GetFiles(ConvertUrlToFullPath(url), searchPattern, (SearchOption)searchOption).Select(ConvertFullPathToUrl).ToArray();
}
#if STRIDE_PLATFORM_IOS
public bool AutoSetSkipBackupAttribute { get; set; }
#endif
/// <inheritdoc/>
public override Stream OpenStream(string url, VirtualFileMode mode, VirtualFileAccess access, VirtualFileShare share = VirtualFileShare.Read, StreamFlags streamType = StreamFlags.None)
{
if (localBasePath != null && url.Split(VirtualFileSystem.DirectorySeparatorChar, VirtualFileSystem.AltDirectorySeparatorChar).Contains(".."))
throw new InvalidOperationException("Relative path is not allowed in FileSystemProvider.");
var filename = ConvertUrlToFullPath(url);
var result = new FileStream(filename, (FileMode)mode, (FileAccess)access, (FileShare)share);
#if STRIDE_PLATFORM_IOS
if (AutoSetSkipBackupAttribute && (mode == VirtualFileMode.CreateNew || mode == VirtualFileMode.Create || mode == VirtualFileMode.OpenOrCreate))
{
Foundation.NSFileManager.SetSkipBackupAttribute(filename, true);
}
#endif
return result;
}
public override DateTime GetLastWriteTime(string url)
{
return File.GetLastWriteTime(ConvertUrlToFullPath(url));
}
}View on GitHub (pinned to 96fad776d2)