Repository navigation
This release updates the rendering engine to GroupDocs.Viewer 26.9.0 and fixes several security issues in the API, the local storage and cache, and the cloud storage providers. Upgrading is strongly recommended for every application where the viewer can be reached by users you do not fully trust.
🔒 Security fixes
Update all GroupDocs.Viewer.UI.* packages to 26.9.0. The fixes are spread across packages, so updating only some of them leaves the others open:
| Issue | Affected applications | Fixed in |
|---|---|---|
| Files outside the storage folder could be read, listed, and overwritten | AddLocalStorage(...) |
GroupDocs.Viewer.UI.Api.Local.Storage |
| Files outside the cache folder could be read through page resource requests, whatever the storage provider | AddLocalCache(...) with HTML rendering (the default) |
GroupDocs.Viewer.UI.Api.Local.Cache, GroupDocs.Viewer.UI.Api |
| Blobs in other containers of the storage account could be read and written | AddAzureBlobStorage(...) |
GroupDocs.Viewer.UI.Api.AzureBlob.Storage |
| File paths could change GroupDocs Cloud API requests | AddCloudStorage(...), AddGroupDocsViewerCloudApi(...) |
GroupDocs.Viewer.UI.Api.Cloud.Storage, GroupDocs.Viewer.UI.Cloud.Api |
| Upload by URL could reach internal network addresses (server-side request forgery) | EnableFileUpload = true (the default) |
GroupDocs.Viewer.UI.Api |
RequireAuthorization() on MapGroupDocsViewerApi had no effect |
applications that protect the API with endpoint conventions | GroupDocs.Viewer.UI.Api |
| Error messages exposed absolute paths on the server | all | GroupDocs.Viewer.UI.Api |
Local storage keeps paths inside the storage folder
A crafted file or folder path, such as one with .. segments or an absolute path, could reach files outside the folder passed to AddLocalStorage. A client could open, list, or overwrite any file the application has access to. Every path received from the client is now resolved inside the storage folder:
- A leading
/(or\on Windows) refers to the storage folder:/reports/q3.docxis<storage folder>/reports/q3.docx. - Paths that resolve outside the storage folder are rejected with
UnauthorizedAccessException. The client receives "Access to the file or folder is denied." - Uploaded files are saved under their file name only. Any folder part of the name sent by the browser is ignored.
Local cache keeps entries inside the cache folder
The local cache builds its file paths from the document path and the page resource name. A crafted resource name could read files outside the cache folder, with any storage provider, and a rooted document path could make the cache create folders and write files outside it.
- Cache keys must be plain file names, and every cache path is checked to stay inside the cache folder.
get-resourcereturns404 Not Foundfor resource names that contain/or\. Resource names produced by the viewer never do.- Documents opened by a rooted path, such as
/doc.pdforC:\doc.pdf, are now cached in a sub-folder of the cache folder, so they are rendered again once. Cached entries for regular relative paths are reused as before.
Azure Blob Storage rejects .. in blob names
The Azure SDK resolves .. segments in blob names, so a file path with .. could read or write blobs in other containers of the same storage account. Paths with .. segments are now rejected with UnauthorizedAccessException.
The Amazon S3 storage rejects such paths too. Amazon S3 treats them as literal keys, but some S3-compatible services resolve them.
GroupDocs Cloud requests escape file paths
File paths were inserted into GroupDocs Cloud API URLs as is, so a path containing ?, #, or .. could change which storage or API route a request goes to. Each path segment is now URL-escaped, and paths with .. segments are rejected. As a side effect, files whose names contain #, ?, or % now open correctly.
Upload by URL reaches public internet addresses only
When a file is uploaded by URL, the server downloads it. Any address was accepted, including loopback, private networks, and cloud metadata endpoints, and the downloaded content could then be opened in the viewer.
- Only public internet addresses are allowed. Loopback, private, link-local (such as
169.254.169.254), and other special-purpose ranges are refused. The address is checked when the connection is opened, so redirects and DNS tricks can't get around it. - Proxy settings (
HTTP_PROXY,HTTPS_PROXY, the system proxy) are not used for these downloads. - The downloaded file can't be larger than the server's request body size limit, the same limit that applies when the file is uploaded directly (30,000,000 bytes by default in Kestrel and IIS).
- Only
httpandhttpsURLs are accepted.
Conventions on MapGroupDocsViewerApi apply to all API endpoints
MapGroupDocsViewerApi returned a builder that dropped every convention added to it, so .RequireAuthorization() left the API, and with it every document, open to anonymous users even when the UI required sign-in (#116). Conventions such as RequireAuthorization(), RequireCors(), or WithMetadata() now apply to all API endpoints.
To require signed-in users, protect both the UI and the API:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapGroupDocsViewerUI(options =>
{
options.UIPath = "/viewer";
options.ApiEndpoint = "/viewer-api";
}).RequireAuthorization();
app.MapGroupDocsViewerApi(options =>
{
options.ApiPath = "/viewer-api";
}).RequireAuthorization();Error messages no longer expose server paths
The default IErrorMessageProvider returned exception messages unchanged, and file system errors contain absolute paths, for example the full path of the storage folder. File system errors now get generic messages, such as "File 'report.docx' was not found." or "Access to the file or folder is denied." All other messages, including those from the rendering engine, are unchanged. A custom IErrorMessageProvider still receives the original exception.
If you can't upgrade right away
-
Set
config.EnableFileUpload = falseto block both uploads and upload by URL. -
Require authentication for every endpoint without authorization metadata, including the viewer API, with a fallback policy:
builder.Services.AddAuthorization(options => options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
The fallback policy also applies to your own endpoints, so mark the public ones with
[AllowAnonymous]or.AllowAnonymous(). -
The path issues in the local storage, local cache, Azure Blob, and GroupDocs Cloud providers have no configuration workaround. Upgrade.
⚠️ Behavior changes
- Rejected paths fail. Paths that leave the storage folder (local storage) or contain
..segments (Azure Blob, Amazon S3, GroupDocs Cloud) now return an error instead of a file. Paths returned by the file browser are not affected. - Upload by URL from internal addresses, or through a proxy, no longer works. Upload such files directly instead.
- Larger URL uploads need a higher request body limit. Downloads above the request body size limit are refused. To allow larger files, raise the limit, for example with
KestrelServerOptions.Limits.MaxRequestBodySize. The same setting applies to direct uploads. - New
400 Bad Requestresponses. Requests without a valid JSON body ("Request body is missing or is not valid JSON.") or without a file ("File is required.") used to fail with500 Internal Server Error. The viewer UI never sends such requests. RequireAuthorization()onMapGroupDocsViewerApinow takes effect. If your application calls it, anonymous API requests are now challenged in the same way as the UI.- No password prompt for missing files. A file that can't be found no longer opens the password dialog when its name contains "password".
🛠️ Other changes
Rendering engine updated to GroupDocs.Viewer 26.9.0
This is a bug-fix release of the engine with no public API changes, and its dependencies are the same as in 26.8.0. It fixes rendering of PPTX (missing characters in HTML, a crash when rendering PPT, a null reference exception on Linux), PDF to HTML (lost graphics, an incorrectly rendered footer graphic), CAD (the default font, rendering exceptions), TEX, EPS, IGS, and PS documents, and reduces stream reads when processing PDF files. See the GroupDocs.Viewer for .NET 26.9 release notes for details.
PSD, PSB, AI, and ONE documents are still not rendered by the cross-platform engine build, as described in the 26.8.0 release notes.
GroupDocs.Viewer.UI.SelfHost.Api.CrossPlatform is not updated
26.8.0 remains the final release of the deprecated package. It depends on GroupDocs.Viewer.UI.SelfHost.Api 26.8.0 or later, and NuGet resolves the lowest version that matches, so a project that references only the CrossPlatform package keeps getting 26.8.0 without the fixes above. Replace the reference, no code changes are needed:
-<PackageReference Include="GroupDocs.Viewer.UI.SelfHost.Api.CrossPlatform" Version="26.8.0" />
+<PackageReference Include="GroupDocs.Viewer.UI.SelfHost.Api" Version="26.9.0" />📦 Packages
All GroupDocs.Viewer.UI packages are available on NuGet at version 26.9.0:
- GroupDocs.Viewer.UI
- GroupDocs.Viewer.UI.Api
- GroupDocs.Viewer.UI.Api.AwsS3.Storage
- GroupDocs.Viewer.UI.Api.AzureBlob.Storage
- GroupDocs.Viewer.UI.Api.Cloud.Storage
- GroupDocs.Viewer.UI.Api.Distributed.Cache
- GroupDocs.Viewer.UI.Api.InMemory.Cache
- GroupDocs.Viewer.UI.Api.Local.Cache
- GroupDocs.Viewer.UI.Api.Local.Storage
- GroupDocs.Viewer.UI.Cloud.Api
- GroupDocs.Viewer.UI.Core
- GroupDocs.Viewer.UI.SelfHost.Api
Thank you for using GroupDocs.Viewer.UI! If you encounter any issues or have suggestions, please don't hesitate to provide feedback here on GitHub or at our Free Support Forum.