Repository: dotnet/runtime
File: src/mono/wasm/host/DevServer/DevServerStartup.cs (C#)

Code before:
                    // When hot reload is enabled, a middleware injects a hot reload script into the response HTML.
                    // We don't want the browser to bypass this injection by using a cached response that doesn't
                    // contain the injected script. In the future, if script injection is removed in favor of a
                    // different mechanism, we can delete this comment and the line below it.
                    // See also: https://github.com/dotnet/aspnetcore/issues/45213
                    fileContext.Context.Response.Headers[HeaderNames.CacheControl] = "no-store";

                    if (options.WebServerUseCrossOriginPolicy)
                    {
                        // Browser multi-threaded runtime requires cross-origin policy headers to enable SharedArrayBuffer.
                        ApplyCrossOriginPolicyHeaders(fileContext.Context);
                    }
                }
            });

            // Add general-purpose file upload endpoint when DEVSERVER_UPLOAD_PATH is set
            string? fileUploadPath = Environment.GetEnvironmentVariable("DEVSERVER_UPLOAD_PATH");
            string? fileUploadPattern = Environment.GetEnvironmentVariable("DEVSERVER_UPLOAD_PATTERN");
            if (!string.IsNullOrEmpty(fileUploadPath) && !string.IsNullOrEmpty(fileUploadPattern))
            {
                // Ensure the upload directory exists
                if (!Directory.Exists(fileUploadPath))
                {
                    Directory.CreateDirectory(fileUploadPath!);
                }
                Regex fileFilter = new Regex(fileUploadPattern!);

                // Route with filename parameter
                endpoints.MapPost("/upload/{filename}", async context =>
                {
                    try
                    {
                        // Get the filename from the route
                        var routeValues = context.Request.RouteValues;
                        string? rawFileName = routeValues["filename"]?.ToString();

                        // skip upload if no name provided or invalid
                        if (string.IsNullOrEmpty(rawFileName) || !fileFilter.IsMatch(rawFileName!))
                        {
                            return;
                        }

                        // Sanitize filename - IMPORTANT: Only use GetFileName to strip any path components
                        // This prevents directory traversal attacks like "../../../etc/passwd"
                        string fileName = Path.GetFileName(rawFileName);

                        if (string.IsNullOrEmpty(fileName))
                        {
                            fileName = $"upload_{Guid.NewGuid():N}";
                        }


Review comment (bug):
This can throw `ArgumentException` if the regex is invalid [doc](https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.-ctor?view=net-10.0#system-text-regularexpressions-regex-ctor). Wrapping in try-catch would help. 

Code after:
                    // When hot reload is enabled, a middleware injects a hot reload script into the response HTML.
                    // We don't want the browser to bypass this injection by using a cached response that doesn't
                    // contain the injected script. In the future, if script injection is removed in favor of a
                    // different mechanism, we can delete this comment and the line below it.
                    // See also: https://github.com/dotnet/aspnetcore/issues/45213
                    fileContext.Context.Response.Headers[HeaderNames.CacheControl] = "no-store";

                    if (options.WebServerUseCrossOriginPolicy)
                    {
                        // Browser multi-threaded runtime requires cross-origin policy headers to enable SharedArrayBuffer.
                        ApplyCrossOriginPolicyHeaders(fileContext.Context);
                    }
                }
            });

            // Add general-purpose file upload endpoint when DEVSERVER_UPLOAD_PATH is set
            string? fileUploadPath = Environment.GetEnvironmentVariable("DEVSERVER_UPLOAD_PATH");
            string? fileUploadPattern = Environment.GetEnvironmentVariable("DEVSERVER_UPLOAD_PATTERN");
            if (!string.IsNullOrEmpty(fileUploadPath) && !string.IsNullOrEmpty(fileUploadPattern))
            {
                // Ensure the upload directory exists
                if (!Directory.Exists(fileUploadPath))
                {
                    Directory.CreateDirectory(fileUploadPath!);
                }
                Regex fileFilter;
                try
                {
                    fileFilter = new Regex(fileUploadPattern!, RegexOptions.Compiled | RegexOptions.CultureInvariant);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException($"DEVSERVER_UPLOAD_PATTERN value '{fileUploadPattern}' is not a valid regular expression: {ex.Message}", ex);
                }

                // Route with filename parameter
                endpoints.MapPost("/upload/{filename}", async context =>
                {
                    try
                    {
                        // Get the filename from the route
                        var routeValues = context.Request.RouteValues;
                        string? rawFileName = routeValues["filename"]?.ToString();

                        // skip upload if no name provided or invalid
                        if (string.IsNullOrEmpty(rawFileName) || !fileFilter.IsMatch(rawFileName!))
                        {
                            context.Response.StatusCode = 403; // Forbidden
                            await context.Response.WriteAsync("Invalid or missing filename for upload.");
                            return;
                        }