Windows · NTFS

NTFS Permissions and ACLs

How NTFS actually decides who gets in — access control lists, inheritance, and the deny rule that trips up almost every “but I gave them Full Control” ticket.

Quick idea: Every file and folder on an NTFS volume carries its own guest list — an access control list made up of individual entries that each allow or deny one trustee a specific set of rights, and the order those entries are checked in decides who actually gets through.
DACL

The discretionary access control list attached to every file and folder — the actual permission data NTFS checks.

ACE

One access control entry inside a DACL: a trustee, a set of rights, and whether those rights are allowed or denied.

Effective Access

What a specific user actually ends up with once every ACE, group membership, and inherited rule is combined.

What Are NTFS Permissions and ACLs?

NTFS permissions are the access rights attached directly to a file or folder on an NTFS (or ReFS) volume. Each object carries a security descriptor, and inside that descriptor sits the DACL — the discretionary access control list — which is the part that actually governs who can read, write, or delete the object. The DACL is a list of ACEs, access control entries, and each ACE names one trustee (a user, group, or computer account) and a permission mask that either allows or denies specific rights.

Think of a DACL as a guest list posted at a locked door. Each ACE is one line on that list — a name, and next to it either “let in” or “keep out” for a specific set of rooms. The doorman doesn’t read the whole list before deciding; he reads it top to bottom and stops the moment he finds a line that settles the question for the person standing in front of him.

That doorman behaviour is not a metaphor for effect — it’s how Windows access checks are actually documented to work. The system walks the DACL in order and stops as soon as it hits an ACE that either explicitly denies one of the requested rights, or a combination of allow ACEs that has now granted all of them. If it reaches the end of the list with a right still unaccounted for, that right is implicitly denied.

Key point: Order inside the DACL is not cosmetic. The same set of ACEs in a different order can produce a different answer for the same user, which is exactly why Windows enforces a preferred, canonical ordering rather than leaving it to whichever tool last wrote the list.

How Inheritance Works

Permissions on NTFS propagate down from a parent folder to the files and subfolders beneath it, so an administrator sets access once at a sensible level in the tree instead of touching every object individually. An ACE created directly on an object is explicit; an ACE that object received automatically from a parent is inherited. Only ACEs marked to propagate actually inherit — the (OI) object-inherit and (CI) container-inherit flags on an ACE control whether files, subfolders, or both pick it up.

Explicit permissions always take precedence over inherited ones on the same object, even when the inherited rule is a deny. That single rule is the most common source of “but the parent folder denies this” tickets: a more specific, explicit allow set directly on a file genuinely overrides a broader deny inherited from three folders up.

Deny Rules and the Canonical ACE Order

Windows defines a preferred order for the ACEs inside a DACL specifically so that a deny ACE reliably behaves like a deny, regardless of which tool wrote it or when:

Order ACE Group
1Explicit deny ACEs
2Explicit allow ACEs
3Inherited deny ACEs, nearest parent first
4Inherited allow ACEs, nearest parent first

This is why the two rules people memorise about NTFS permissions — “explicit beats inherited” and “deny beats allow” — are really the same underlying mechanism seen from two angles. An explicit deny sits at position 1 and is checked before anything else, including an explicit allow for the same trustee. But an explicit allow (position 2) is still checked before any inherited deny (position 3), which is exactly how a file-level explicit allow can override a folder-level inherited deny.

Important: “Deny always wins” is only true when the deny and the allow are in the same group — both explicit, or both inherited. Across groups, explicit always wins over inherited, allow or deny either way.

Why Active Directory and Windows Server Care

NTFS permissions rarely stand alone in a domain environment. The trustees in every ACE are Active Directory security identifiers, so a broken or overly-permissive DACL on a file server is only as sound as the group it points at. Assigning permissions to AD security groups rather than individual users is standard practice for exactly this reason — it keeps the ACL itself stable while access rises and falls with group membership, and it means a single group change updates every file and folder that references it instead of requiring a re-walk of the tree.

SYSVOL is the sharpest example of NTFS ACLs and Active Directory intersecting directly: Group Policy templates and scripts live on an NTFS volume, replicated by DFS Replication, and their effective delivery to every domain-joined machine depends on the NTFS permissions on those files staying correct across every domain controller. A DACL that drifts on one DC’s copy of SYSVOL is a Group Policy problem wearing an NTFS permissions disguise.

Viewing and Setting Permissions — GUI and PowerShell

In the GUI, right-click a file or folder, open Properties, and go to the Security tab for a simplified allow/deny view, or click Advanced to reach Advanced Security Settings — the dialog that shows the raw ACE list, each entry’s inheritance source, and lets you disable inheritance on an object while choosing whether to keep the inherited ACEs as new explicit ones or drop them entirely.

From the command line, icacls is the current tool for reading and writing DACLs — it replaces the older, deprecated cacls. The permission mask uses simple letters for basic rights (F full, M modify, RX read & execute, R read, W write) and parenthesised inheritance flags for how an ACE propagates:

Flag Meaning
(I)Inherited — this ACE came from a parent container, not set explicitly here.
(OI)Object inherit — files inside this folder inherit the ACE.
(CI)Container inherit — subfolders inside this folder inherit the ACE.
(IO)Inherit only — propagates to children but does not apply to this object itself.
(NP)Don’t propagate — children inherit it, but their own children do not.

PowerShell reaches the same security descriptors through Get-Acl and Set-Acl, both part of the built-in Microsoft.PowerShell.Security module and usable against the FileSystem and Registry providers. Get-Acl returns an object representing the descriptor; Set-Acl takes a -Path (or -InputObject, added in Windows PowerShell 3.0) and an -AclObject to apply. This makes copying a known-good ACL from one object to another a two-line operation instead of a manual permissions rebuild.

Calculating Effective Access

With inheritance, group membership, and deny rules all stacking up, working out what a specific user can actually do by reading the ACE list line by line gets unreliable fast. The Effective Access tab inside Advanced Security Settings does that calculation for you: pick a user, group, or device, and it walks every applicable ACE — including the ones inherited from group membership — to show a resulting permission set. It works on both NTFS and ReFS volumes, and on a domain it can factor in AD and device claims for Dynamic Access Control scenarios, a capability that arrived alongside DAC itself in Windows Server 2012.

Practical note: Effective Access is documented as an approximation, not a guarantee. It always includes the Everyone group in the calculation unless the selected trustee is Anonymous Logon, and it cannot account for logon-type-specific access — a user connecting over SMB gets the network logon SID applied at sign-in time, which the tool has no way to simulate for a user who isn’t actually connected.

Commands Cheat Sheet

# View the DACL of a folder, including inheritance source
icacls "D:\Shares\Finance"

# Grant a group Modify rights, applied to this folder, subfolders, and files
icacls "D:\Shares\Finance" /grant "CORP\Finance-RW:(OI)(CI)M"

# Explicitly deny a group, regardless of any allow granted elsewhere
icacls "D:\Shares\Finance" /deny "CORP\Contractors:(OI)(CI)W"

# Remove every ACE — allow and deny — for a specific trustee
icacls "D:\Shares\Finance" /remove "CORP\OldTeam"

# Reset a folder tree back to inherited-only permissions
icacls "D:\Shares\Finance" /reset /T /C

# Save the current DACLs of a tree to a file, for backup or comparison
icacls "D:\Shares\Finance\*" /save finance-acl-backup.txt /T

# Restore previously saved DACLs onto the same tree
icacls "D:\Shares\Finance" /restore finance-acl-backup.txt

# Read a DACL with PowerShell and show it as SDDL
Get-Acl "D:\Shares\Finance" | Format-List -Property PSPath, Sddl

# Copy the DACL from one folder onto another
Get-Acl "D:\Shares\Finance" | Set-Acl -Path "D:\Shares\Finance-New"
Production note: icacls /reset discards every explicit ACE on the target and replaces it with whatever inheritance alone would produce. Run it with /save first on anything that matters, so a bad reset has a rollback path.

Troubleshooting Cheat Sheet

Symptom Likely Cause Fix
User has access despite a group they’re in being denied An explicit allow exists directly on the object (or closer in the tree), and explicit always outranks inherited. Check the Effective Access tab, then look for an explicit ACE on the object itself before assuming the deny is broken.
Full Control granted, user still can’t write Share permissions are more restrictive than NTFS permissions, and the two intersect rather than add. Check the Sharing tab’s permissions separately — the effective access over the network is whichever of share or NTFS is more restrictive.
Permissions look right in the GUI but a script still gets Access Denied The account running the script isn’t the account whose permissions were checked in the GUI. Confirm the actual execution identity: whoami in the same context, or check the service account under which a scheduled task runs.
Moved files lost their old permissions A move within the same NTFS volume keeps explicit ACEs, but a move across volumes is a copy-then-delete and inherits fresh permissions from the new parent. After a cross-volume move, re-check the DACL with icacls rather than assuming it travelled with the file.
Removing a user from a group doesn’t remove their access An explicit ACE was set directly for that user at some point, independent of any group membership. Search for the user’s SID directly on the object: icacls "D:\Shares\Finance" /findsid <SID or account>.

Final Thoughts

Most NTFS permission confusion comes from treating the DACL as an unordered set of rules instead of an ordered list that gets read top to bottom until a question is answered. Once the canonical order — explicit deny, explicit allow, inherited deny, inherited allow — is the mental model, “deny wins” and “explicit wins” stop looking like two separate rules and become one consistent explanation for almost every access surprise.

Lean on the Effective Access tab before touching an ACL by hand, and on icacls /save before running anything that resets or removes permissions at scale. Both exist because the failure mode for getting this wrong in a production file server is rarely “too little access” — it’s the far more disruptive “everyone loses access to something they needed an hour ago.”

Key takeaway: NTFS access checks stop at the first ACE that settles the question, in the order explicit deny → explicit allow → inherited deny → inherited allow. An explicit rule on the object itself always beats an inherited one, deny or allow either way.
Next in this series

Next, we can cover Volume Shadow Copy Service — how Windows takes point-in-time snapshots of these same NTFS volumes, and what that means for restoring a file without touching the live permissions on it.