@@ -68,19 +68,41 @@ module SchemaReader =
6868 then
6969 failwithf " Cannot fetch schemas from localhost/loopback addresses: %s (set SsrfProtection=false for development)" host
7070
71- let validateContentType ( contentType : Headers.MediaTypeHeaderValue ) =
72- if not ( isNull contentType) then
71+ let validateContentType ( ignoreSsrfProtection : bool ) ( contentType : Headers.MediaTypeHeaderValue ) =
72+ // Skip validation if SSRF protection is disabled
73+ if ignoreSsrfProtection || isNull contentType then
74+ ()
75+ else
7376 let mediaType = contentType.MediaType.ToLowerInvariant()
7477
75- if
76- not (
77- mediaType.Contains " json"
78- || mediaType.Contains " yaml"
79- || mediaType.Contains " text"
80- || mediaType.Contains " application/octet-stream"
81- )
82- then
83- failwithf " Invalid Content-Type for schema: %s . Expected JSON or YAML." mediaType
78+ // Allow only Content-Types that are valid for OpenAPI/Swagger schema files
79+ // This prevents SSRF attacks where an attacker tries to make the provider
80+ // fetch and process non-schema files (HTML, images, binaries, etc.)
81+ let isValidSchemaContentType =
82+ // JSON formats
83+ mediaType = " application/json"
84+ || mediaType = " application/json; charset=utf-8"
85+ || mediaType.StartsWith " application/json;"
86+ // YAML formats
87+ || mediaType = " application/yaml"
88+ || mediaType = " application/x-yaml"
89+ || mediaType = " text/yaml"
90+ || mediaType = " text/x-yaml"
91+ || mediaType.StartsWith " application/yaml;"
92+ || mediaType.StartsWith " application/x-yaml;"
93+ || mediaType.StartsWith " text/yaml;"
94+ || mediaType.StartsWith " text/x-yaml;"
95+ // Plain text (sometimes used for YAML)
96+ || mediaType = " text/plain"
97+ || mediaType.StartsWith " text/plain;"
98+ // Generic binary (fallback for misconfigured servers)
99+ || mediaType = " application/octet-stream"
100+ || mediaType.StartsWith " application/octet-stream;"
101+
102+ if not isValidSchemaContentType then
103+ failwithf
104+ " Invalid Content-Type for schema: %s . Expected JSON or YAML content types only. This protects against SSRF attacks. Set SsrfProtection=false to disable this validation."
105+ mediaType
84106
85107 let readSchemaPath ( ignoreSsrfProtection : bool ) ( headersStr : string ) ( schemaPathRaw : string ) =
86108 async {
@@ -112,7 +134,7 @@ module SchemaReader =
112134 let! response = client.SendAsync request |> Async.AwaitTask
113135
114136 // Validate Content-Type to ensure we're parsing the correct format
115- validateContentType response.Content.Headers.ContentType
137+ validateContentType ignoreSsrfProtection response.Content.Headers.ContentType
116138
117139 return ! response.Content.ReadAsStringAsync() |> Async.AwaitTask
118140 }
@@ -171,7 +193,7 @@ module SchemaReader =
171193 let! response = client.SendAsync( request) |> Async.AwaitTask
172194
173195 // Validate Content-Type to ensure we're parsing the correct format
174- validateContentType response.Content.Headers.ContentType
196+ validateContentType ignoreSsrfProtection response.Content.Headers.ContentType
175197
176198 return ! response.Content.ReadAsStringAsync() |> Async.AwaitTask
177199 }
0 commit comments