Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}

steps:
Expand Down
27 changes: 19 additions & 8 deletions src/SwaggerProvider.DesignTime/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,10 @@ module SchemaReader =
let possibleFilePath =
try
if Path.IsPathRooted resolvedPath then
// Already an absolute path
if File.Exists resolvedPath then Some resolvedPath else None
// Already a rooted path - normalize it to handle .. and . components
// This is important on Windows where paths like D:\foo\..\bar need normalization
let normalized = Path.GetFullPath resolvedPath
if File.Exists normalized then Some normalized else None
else
// Try to resolve relative paths (e.g., paths with ../ or from __SOURCE_DIRECTORY__)
let resolved = Path.GetFullPath resolvedPath
Expand All @@ -196,12 +198,21 @@ module SchemaReader =
| ex -> return failwithf "Error reading schema file '%s': %s" filePath ex.Message
| None ->
// Handle as remote URL (HTTP/HTTPS)
let checkUri = Uri(resolvedPath, UriKind.RelativeOrAbsolute)
// Only treat truly local paths as local files (no scheme or relative paths)
// Reject file:// scheme as unsupported to prevent SSRF attacks
let isLocalFile = not checkUri.IsAbsoluteUri

if isLocalFile then
// First check if this looks like a local file path (Windows or Unix)
// On Windows, paths like D:\path are parsed as URIs with scheme "D", so we need special handling
let looksLikeWindowsPath =
resolvedPath.Length >= 2
&& Char.IsLetter(resolvedPath.[0])
&& resolvedPath.[1] = ':'

let looksLikeUnixAbsolutePath = resolvedPath.StartsWith("/")

// If it looks like a local file path, treat it as such (file not found)
if
looksLikeWindowsPath
|| looksLikeUnixAbsolutePath
|| not(resolvedPath.Contains("://"))
then
// If we reach here with a local file that wasn't found, report the error
return failwithf "Schema file not found: %s" resolvedPath
else
Expand Down
Loading