Introduction

IIS application pools run under specific identity accounts (ApplicationPoolIdentity, NetworkService, or custom domain accounts). When the pool identity lacks NTFS permissions to access web application files, configuration files, or network shares, the web application returns HTTP 500 errors with access denied messages. This is a common issue after deploying new applications, moving content, or changing app pool identities.

Symptoms

  • HTTP 500.19 error with Config Error: Cannot read configuration file due to insufficient permissions
  • Application returns HTTP 500 with Access to the path 'C:\inetpub\wwwroot\config' is denied
  • Event Viewer shows w3wp.exe access denied errors under Application log
  • ASP.NET application fails with UnauthorizedAccessException
  • File upload feature fails with Access is denied

Common Causes

  • App pool identity changed without updating NTFS ACLs on web root
  • ApplicationPoolIdentity uses virtual account IIS AppPool\PoolName not recognized by older ACLs
  • Network share accessed by app pool identity lacks delegation configuration
  • Inheritance disabled on parent directory blocking permission propagation
  • Antivirus or security software resetting permissions on web content

Step-by-Step Fix

  1. 1.Identify the application pool identity:
  2. 2.```powershell
  3. 3.Import-Module WebAdministration
  4. 4.Get-ItemProperty IIS:\AppPools\MyAppPool -Name processModel
  5. 5.`
  6. 6.Check current permissions on the web root:
  7. 7.```powershell
  8. 8.Get-Acl "C:\inetpub\wwwroot\myapp" | Format-List
  9. 9.# Look for IIS AppPool\MyAppPool in the access list
  10. 10.`
  11. 11.Grant the app pool identity read access:
  12. 12.```powershell
  13. 13.$acl = Get-Acl "C:\inetpub\wwwroot\myapp"
  14. 14.$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
  15. 15."IIS AppPool\MyAppPool",
  16. 16."ReadAndExecute",
  17. 17."ContainerInherit,ObjectInherit",
  18. 18."None",
  19. 19."Allow"
  20. 20.)
  21. 21.$acl.SetAccessRule($rule)
  22. 22.Set-Acl "C:\inetpub\wwwroot\myapp" $acl
  23. 23.`
  24. 24.Grant write access to specific subdirectories if needed:
  25. 25.```powershell
  26. 26.$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
  27. 27."IIS AppPool\MyAppPool",
  28. 28."Modify",
  29. 29."ContainerInherit,ObjectInherit",
  30. 30."None",
  31. 31."Allow"
  32. 32.)
  33. 33.$acl = Get-Acl "C:\inetpub\wwwroot\myapp\uploads"
  34. 34.$acl.SetAccessRule($rule)
  35. 35.Set-Acl "C:\inetpub\wwwroot\myapp\uploads" $acl
  36. 36.`
  37. 37.Test with ICACLS from command prompt:
  38. 38.```cmd
  39. 39.icacls "C:\inetpub\wwwroot\myapp" /grant "IIS AppPool\MyAppPool":(OI)(CI)RX
  40. 40.icacls "C:\inetpub\wwwroot\myapp\uploads" /grant "IIS AppPool\MyAppPool":(OI)(CI)M
  41. 41.`
  42. 42.Recycle the application pool and test:
  43. 43.```powershell
  44. 44.Restart-WebAppPool MyAppPool
  45. 45.# Test the site in a browser
  46. 46.`

Prevention

  • Use a deployment script that sets permissions every time content is deployed
  • Document required ACLs for each application in a runbook
  • Use custom service accounts for app pools that need network resource access
  • Configure file system auditing on web roots to detect permission changes
  • Test new deployments in staging with the same app pool identity as production