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