Web applications frequently need to handle file uploads and downloads and serve static resources. If not properly secured, they become vulnerable to path traversal and directory browsing attacks, which attackers can exploit to gain unauthorized access to sensitive files.

In this article, we’ll understand these attacks and see practical ways to mitigate them in ASP.NET Core.

What Are Path Traversal and Directory Browsing?

Mitigation Strategies in ASP.NET Core

1. Disable Directory Browsing

By default, directory browsing should be disabled in production.
In Program.cs (or Startup.cs in older versions):

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// Do NOT enable directory browsing
// app.UseDirectoryBrowser(); //  Avoid this

app.UseStaticFiles(); // Safe for serving static content

app.Run();

If you must allow browsing in a specific directory, configure it explicitly and restrict access using Authorization Policies.

2. Sanitize File Paths

When handling file upload or download requests, never trust user input for file paths. Use safe methods like Path.GetFileName or Path.Combine.

[HttpGet("download")]
public IActionResult DownloadFile(string fileName)
{
    // Sanitize the input
    var safeFileName = Path.GetFileName(fileName); // Removes directory traversal chars
    var uploads = Path.Combine(Directory.GetCurrentDirectory(), "uploads");
    var filePath = Path.Combine(uploads, safeFileName);

    if (!System.IO.File.Exists(filePath))
        return NotFound();

    var contentType = "application/octet-stream";
    return PhysicalFile(filePath, contentType, safeFileName);
}

Path.GetFileName ensures only the file name is used, preventing ../ tricks.

3. Restrict File Upload Paths

When saving uploaded files, lock them into a safe directory:

[HttpPost("upload")]
public async Task<IActionResult> UploadFile(IFormFile file)
{
    if (file == null || file.Length == 0)
        return BadRequest("Invalid file.");

    var uploads = Path.Combine(Directory.GetCurrentDirectory(), "uploads");

    // Ensure directory exists
    if (!Directory.Exists(uploads))
        Directory.CreateDirectory(uploads);

    var safeFileName = Path.GetFileName(file.FileName);
    var filePath = Path.Combine(uploads, safeFileName);

    using (var stream = new FileStream(filePath, FileMode.Create))
    {
        await file.CopyToAsync(stream);
    }

    return Ok("File uploaded successfully.");
}

4. Validate File Types and Extensions

Attackers may upload scripts (.aspx, .php, .exe).
Block dangerous file extensions:

string[] allowedExtensions = { ".jpg", ".png", ".pdf" };
string ext = Path.GetExtension(file.FileName).ToLowerInvariant();

if (!allowedExtensions.Contains(ext))
{
    return BadRequest("File type not allowed.");
}

5. Use Static File Middleware Safely

If serving files:

app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        // Prevent caching of sensitive files
        ctx.Context.Response.Headers.Append("Cache-Control", "no-store");
    }
});

6. Harden web.config and Sensitive Files

Although ASP.NET Core doesn’t use web.config for hosting settings on Kestrel, IIS environments still do. Ensure sensitive files are not accessible via HTTP.

Add in web.config (for IIS hosting):

<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <hiddenSegments>
          <add segment="bin"/>
          <add segment="App_Data"/>
          <add segment="App_Code"/>
        </hiddenSegments>
      </requestFiltering>
    </security>
  </system.webServer>
</configuration>

7. Apply Least Privilege on File System

Best Practices Checklist

Conclusion

Path traversal and directory browsing are serious threats that can compromise your application and server. By disabling directory browsing, sanitizing paths, validating uploads, and enforcing least privilege, you can secure your ASP.NET Core applications against these common attacks.