0X00000228

ACL Error 0X00000228: Missing Minimum Info Fix

Windows throws this when an ACL you pass to a security function is incomplete. Quick fix: rebuild the ACL with proper inheritance flags.

Yeah, this error is a pain — you're trying to set permissions on something and Windows just refuses, spitting back 0x00000228. The ACL you passed didn't have the minimum required info. Let me show you the fix.

The Direct Fix

The fastest way out is to rebuild the ACL from scratch using PowerShell. Don't waste time trying to patch the broken one — Windows is telling you the whole structure is wrong.

# Get the current ACL and rewrite it properly
$path = "C:\Path\To\Your\File"  # Replace with your target
$acl = Get-Acl -Path $path

# Create a fresh AccessRule with proper inheritance
$identity = "BUILTIN\Administrators"
$fileSystemRights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritanceFlags = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$propagationFlags = [System.Security.AccessControl.PropagationFlags]::None
$accessControlType = [System.Security.AccessControl.AccessControlType]::Allow

$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    $identity, $fileSystemRights, $inheritanceFlags, $propagationFlags, $accessControlType
)

# Clear existing rules and add the new one
$acl.SetAccessRuleProtection($false, $false)
$acl.ResetAccessRule($accessRule)

# Apply it
Set-Acl -Path $path -AclObject $acl

Run this as Administrator. If it throws Access Denied, you need SeSecurityPrivilege — more on that below.

Why This Works

What's actually happening here is that the original ACL was missing required inheritance flags or propagation flags. Windows security model demands that every ACE in an ACL has these fields populated. When you pass an ACL via API calls like SetSecurityInfo or NtSetSecurityObject and any ACE is incomplete, you get 0x00000228.

The reason the PowerShell script above works is that it explicitly sets ContainerInherit and ObjectInherit with PropagationFlags.None. That's the minimum valid combination for a folder that needs to propagate permissions to children. Without those flags, Windows sees the ACE as "not sufficiently defined" and refuses to apply it.

Also note: SetAccessRuleProtection($false, $false) tells Windows "this ACL isn't protected from parent inheritance." If you set it to $true, you'd be adding explicit deny rules as well, which isn't what we want here.

Less Common Variations

1. Registry ACLs

Same error can show up when editing registry keys. The fix is similar but uses RegistryAccessRule instead of FileSystemAccessRule:

$path = "HKLM:\SOFTWARE\YourKey"
$acl = Get-Acl -Path $path
$identity = "BUILTIN\Administrators"
$accessRule = New-Object System.Security.AccessControl.RegistryAccessRule(
    $identity, "FullControl", "ContainerInherit", "None", "Allow"
)
$acl.ResetAccessRule($accessRule)
Set-Acl -Path $path -AclObject $acl

Watch out: registry ACLs don't allow ObjectInherit — only ContainerInherit makes sense here.

2. Service ACLs (SERVICE_SECURITY_INFO)

If you hit this when managing services via ChangeServiceConfig2, the fix is the same principle but using SDDL string format directly:

# Use SDDL string with all required fields
$sddl = "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)"
$sd = New-Object System.Security.AccessControl.CommonSecurityDescriptor $false, $false, $sddl
# Pass $sd to SetServiceObjectSecurity

That SDDL grants full control to SYSTEM and Administrators — the bare minimum Windows expects.

3. When SeSecurityPrivilege Is Missing

Sometimes you'll get 0x00000228 and an access denied, even as Administrator. That's because the security descriptor you're trying to set requires SeSecurityPrivilege (the right to manage SACLs). Here's how to enable it:

# Enable SeSecurityPrivilege for current process
$privilege = "SeSecurityPrivilege"
$tokenHandle = [System.Security.Principal.WindowsIdentity]::GetCurrent().Token
$luid = New-Object UInt64
[advapi32]::LookupPrivilegeValue($null, $privilege, [ref]$luid)
$tp = New-Object UInt64 2
[advapi32]::AdjustTokenPrivileges($tokenHandle, $false, [ref]$tp, 0, [IntPtr]::Zero, [IntPtr]::Zero)

You'll need P/Invoke for advapi32 functions — that code snippet is a sketch; in reality use System.Security.Principal.WindowsIdentity.RunAs with a new identity that has the privilege, or just run PowerShell as a user who already has it (usually LocalSystem).

Prevention

Stop building ACLs by hand unless you really have to. Use Get-Acl on a known-good object as a template, then modify only the identity and rights fields. That way you inherit all the correct flags automatically.

If you're writing C++ or C# code that calls SetSecurityInfo, always initialize your SECURITY_DESCRIPTOR with InitializeSecurityDescriptor and set the DACL via SetSecurityDescriptorDacl — don't skip the control flags. A null or partial descriptor will trigger this error every time.

And test on a VM first. This error can lock you out of files or registry keys if applied wrong. Trust me, been there.

Related Errors in Windows Errors
0X000020E4 Fix ERROR_DS_CANT_FIND_EXPECTED_NC (0X000020E4) fast 0X00000275 Fix 0x00000275: Deny-Only Group Can't Be Enabled 0XC00D279C Fix NS_E_DRM_MALFORMED_CONTENT_HEADER (0XC00D279C) Fast 0XC00D284A NS_E_DRM_LICENSE_INITIALIZATION_ERROR (0XC00D284A) fix

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.