sd

sd is the command-line tool for working with security descriptors on files. Its subcommands edit owners, DACLs, SACLs, integrity labels and inheritance. The show subcommand queries only owner, group, DACL and the integrity-label view; it does not read the full SACL.

sd subcommand path [arguments]
$ sd show ./report.txt
$ sd allow ./report.txt alice:read
$ sd owner ./report.txt BA

Where ls -l shows a file's owner and a summary, and cp --sd carries selected descriptor components (owner, DACL, and SACL), sd is the tool that edits the descriptor directly.

The subcommands #

GroupSubcommandDoes
InspectshowShow owner, group, DACL and the integrity-label view on a path.
checkSimulate an access check against the path.
DACLallowAdd an allow rule for one or more principals.
denyAdd a deny rule for one or more principals.
removeDrop every DACL rule for the named principals.
AuditingauditAdd an audit rule to the SACL.
unauditDrop every SACL rule for the named principals.
OwnershipownerSet the descriptor's owner.
groupSet the descriptor's group.
IntegrityintegritySet the mandatory integrity label.
InheritanceinheritTurn inheritance protection on or off.
resetDrop the file's own rules and re-inherit from the parent.
propagatePush inheritance down to descendants.
WholesalesetWrite the supplied descriptor components; kernel merge and validation rules apply.

Naming a principal #

Wherever a subcommand takes a PRINCIPAL, it accepts any of:

FormExampleMeaning
@self@selfThe user SID of the token running sd.
@owner@ownerA placeholder that the access check substitutes with the file's own owner.
A well-known labelEveryone, Administrators, LocalSystemA named built-in principal.
A two-letter aliasWD, BA, SYThe short alias for a well-known principal.
A raw SIDS-1-5-32-544Any SID, written out in full.

See SIDs for what these are.

Naming permissions #

Wherever a subcommand takes PERMS, several notations are accepted, and may be mixed:

FormExampleMeaning
Single lettersrwx, r, mr read, w write, x execute, d delete, m modify, f full, c change-permissions, o take-ownership.
Wordsread,write, modifyThe same set, spelled out.
Fine-grained namesread-data,append,traverseIndividual low-level rights, for precise rules.
Raw hex0x1F01FFAn access mask written directly.

Run letters together (rwx) or separate names with commas (read,write,execute).

Inspecting #

sd show #

Queries the owner, group, DACL and mandatory integrity-label subset on a path. It selects OWNER | GROUP | DACL | LABEL, not the full SACL. Audit ACEs and other non-label SACL entries are outside this view, even when the caller has authority to read them.

$ sd show ./report.txt
FlagEffect
--sddlRender the queried components as SDDL.
--rawRender SIDs in raw S-1-… form only; this is not raw descriptor export.
--labelRender SIDs as their labels where known.
--allAdd the queried byte length and, in human output, the raw control value.
--jsonEmit JSON for the selected view.

These flags change formatting, not the component selection. A SACL heading or JSON key contains the selected label view, not the audit SACL. --all does not request additional components, and there is no full-SACL/export selector for show.

Human and ordinary JSON output are summaries: callback condition payloads are not serialized, and other ACE bodies are represented by their length. Matching output does not prove complete descriptor equality. --sddl still formats only the queried subset; do not use it as a full backup to replay with sd set. If audit entries or complete metadata verification are required, this command does not provide that evidence.

sd check #

Simulates an access decision: "would this access be allowed?" — without performing it.

$ sd check ./report.txt write
$ sd check ./report.txt read --pid 4821 --explain
Argument / flagEffect
PERMSThe access to test for.
--pid PIDCheck against process PID's token instead of your own.
--explainShow why the decision came out as it did — the rule-by-rule walk.

sd check is the first thing to reach for when an access is denied and you do not know why. --explain walks the descriptor the same way the kernel does.

Changing the DACL #

The DACL is the list of allow and deny rules. These three subcommands edit it.

sd allow and sd deny #

Add an allow (or deny) rule for one or more PRINCIPAL:PERMS pairs.

$ sd allow ./report.txt alice:read bob:rw
$ sd deny  ./report.txt Everyone:write
FlagEffect
--flags LISTACE inheritance flags — CI container-inherit, OI object-inherit, NP no-propagate, IO inherit-only; none clears them.
--if EXPRMake it a conditional rule, applied only when EXPR is true.
--replaceDrop any existing rules for this principal and kind first, instead of appending.
--recursive, -rApply to every descendant of the path.

The DACL is evaluated in order: the first matching ACE that decides a right wins for that right. A later deny does not undo an earlier allow, and a later allow does not undo an earlier deny. See DACL evaluation.

sd remove #

Drops every DACL rule — allow and deny — for the named principals.

$ sd remove ./report.txt bob carol
FlagEffect
--allow-emptyPermit the result to be a present-but-empty DACL, which denies everyone. Without this, sd refuses to produce one.
--recursive, -rApply to every descendant.

Auditing #

sd audit and sd unaudit #

The SACL holds audit rules — see The SACL. sd audit adds one; sd unaudit drops every SACL rule for the named principals.

$ sd audit ./secrets.db Everyone:write:failure

An audit spec is PRINCIPAL:PERMS:WHEN, where WHEN is success, failure, or both — which outcomes to log. sd audit takes the same --flags, --if, --replace, and -r options as sd allow.

Ownership #

sd owner and sd group #

Set the descriptor's owner or group SID.

$ sd owner ./report.txt alice
$ sd group ./report.txt Administrators

Both take a single PRINCIPAL and accept -r. Changing an owner is itself an access-controlled act — see Ownership.

Integrity #

sd integrity #

Sets the file's mandatory integrity label.

$ sd integrity ./report.txt high

The level is one of untrusted, low, medium, medium-plus, high, system, protected. The standard catalog is five levels (untrusted, low, medium, high, system); medium-plus (RID 8448) and protected (RID 20480) are non-standard Windows-compatibility levels — the kernel compares any S-1-16-<rid> numerically.

FlagEffect
--policy BITSThe label's policy bits, comma-separated: NW no write-up, NR no read-up, NX no execute-up.
--recursive, -rApply to every descendant.

For what the label does, see Mandatory integrity control.

Inheritance #

sd inherit #

Turns inheritance protection on or off — the + mark ls -l shows.

$ sd inherit off ./report.txt    # lock the file; stop inheriting
$ sd inherit on  ./report.txt    # let it inherit from its parent again

inherit on permits inheritance from the parent directory; inherit off protects the file while keeping its current rules. Neither creates a live link to the parent: the child stores its own descriptor, and later parent changes require explicit propagation to existing children. See Inheritance.

FlagEffect
--strip-inheritedWhen turning protection off, also drop the inherited rules already on the file.
--recursive, -rApply to every descendant.

sd reset #

Drops the file's own explicit rules and its protection, and rebuilds its DACL purely from what the parent directory hands down — returning the file to "inherits everything".

sd propagate #

Pushes this directory's inheritable rules down into its descendants, refreshing what they inherit. Use it after changing a directory's rules so the children pick up the change. Each descendant gets what it would get if it were created now: a CREATOR OWNER rule gives that descendant's own owner, and generic rights are translated into file rights.

A descendant that protects its rules (sd inherit off) is left as it is and counted in the summary, though the files below it are still refreshed from it. A descendant that can't be changed is reported, and the walk carries on.

FlagEffect
--saclPush the audit rules (SACL) down as well. Needs SeSecurityPrivilege.
--jsonReport what was pushed, protected and refused as JSON.

See Inheritance for the full model.

Replacing the whole descriptor #

sd set #

Writes the supplied descriptor components. On a file with a valid descriptor, the kernel merges selected components and selected control bits rather than replacing every descriptor byte. Missing or invalid file security descriptors use a separate privileged replacement path; see the kernel contract. Do not treat the selected output of sd show --sddl as a complete input backup.

$ sd set ./report.txt 'O:BAG:BAD:P(A;;FA;;;BA)(A;;0x1200a9;;;BU)'
Argument / flagEffect
SDDLThe new descriptor as an SDDL string. - reads it from standard input.
--binary FILEInstead of SDDL, read the raw descriptor bytes from FILE (- for standard input).
--components LISTOverride which parts of the descriptor (owner, group, DACL, SACL) the operation writes.

Common flags #

These apply across the subcommands:

FlagEffect
--recursive, -rApply the change to every descendant of the path. Implies --no-follow-symlinks.
--no-follow-symlinks, -POperate on a symbolic link itself, not the file it points to.
--jsonEmit JSON instead of human-readable output.

A recursive run stamps a tree, and a symbolic link is a node in that tree rather than a route out of it. So -r operates on link inodes and does not descend through them: the links themselves get the descriptor you asked for, and nothing outside the tree is touched. This matters on Peios more than it might elsewhere, because /usr/bin is around 170 links into a single multi-call binary — a recursive grant that followed them would stamp that one binary repeatedly and leave every command unreachable.

Name a path without -r and sd follows it, because naming a symbolic link is how you say you mean its target. If you want the link itself, pass -P.

seed-sd stamps trees the same way, so the two tools agree about what a symbolic link is.

Exit status #

CodeMeaning
0The operation succeeded — or, for sd check, the access would be allowed.
non-zeroThe operation failed, the path was unreachable, or — for sd check — the access would be denied.

Source and version scope #

The show selection and rendering described here are checked against peiosutils 0.8.18, commit 3344d469. This source review does not identify the version installed on a machine or establish a runtime-tested metadata export and restore procedure.

Edit this page