@@ -74,7 +74,8 @@ public ExtensionService(
7474 throw new ArgumentNullException ( nameof ( serverUrl ) ) ;
7575
7676 _downloadPath = downloadPath ;
77- _serverUrl = serverUrl . TrimEnd ( '/' ) ; // Remove trailing slash for consistent URL construction
77+ // Remove trailing slashes for consistent URL construction (only forward slashes expected in URLs)
78+ _serverUrl = serverUrl . TrimEnd ( '/' ) ;
7879 _updateQueue = updateQueue ?? throw new ArgumentNullException ( nameof ( updateQueue ) ) ;
7980 _downloadTimeout = downloadTimeout ;
8081 _hostVersion = hostVersion ;
@@ -309,8 +310,9 @@ public async Task<HttpResponseDTO<DownloadExtensionDTO>> Download(string id)
309310
310311 var descriptor = operation . Extension . Descriptor ;
311312
312- // Construct download URL from server URL and extension ID
313- var downloadUrl = $ "{ _serverUrl } /Download/{ descriptor . Name } ";
313+ // Construct download URL from server URL and extension ID (URL-encoded for safety)
314+ var encodedExtensionName = Uri . EscapeDataString ( descriptor . Name ) ;
315+ var downloadUrl = $ "{ _serverUrl } /Download/{ encodedExtensionName } ";
314316
315317 try
316318 {
@@ -447,8 +449,9 @@ private ExtensionDTO MapToExtensionDTO(AvailableExtension extension, Version? ho
447449 isCompatible = _validator . IsCompatible ( descriptor ) ;
448450 }
449451
450- // Construct download URL from server URL
451- var downloadUrl = $ "{ _serverUrl } /Download/{ descriptor . Name } ";
452+ // Construct download URL from server URL (URL-encoded for safety)
453+ var encodedExtensionName = Uri . EscapeDataString ( descriptor . Name ?? string . Empty ) ;
454+ var downloadUrl = $ "{ _serverUrl } /Download/{ encodedExtensionName } ";
452455
453456 return new ExtensionDTO
454457 {
0 commit comments