Expand description
Who may write inside the platform default runner root, and how that is established.
runner_root decides where runner workspaces go and
deliberately mutates nothing: 02-target-architecture.md keeps “directory
creation and the narrowly scoped default-root ACL operation” as explicit
application steps that happen after validation passes. This module is that
step, and it is the only place in the workspace that creates or
re-permissions a runner root.
§The threat, stated exactly
04-security-recovery.md lists it in one line: “%SystemDrive%\rman is
writable by unrelated local users.” That is not hypothetical, it is the
default on every Windows host. The security descriptor of C:\ carries
an inherit-only ACE of roughly this shape:
(A;OICIIO;SDGXGWGR;;;AU)— Authenticated Users, delete plus generic read/write/execute, inherited
by every child of C:\. A directory created there with inheritance left on
is therefore writable by every account that can log in, including the
account a hostile workflow’s own leftovers could be running as. Runner
workspaces are executable content that a later job re-enters, so this is a
code-execution boundary rather than a tidiness one.
The control is one character: P, the SE_DACL_PROTECTED flag, which
severs inheritance. Everything else in this module exists to apply it
without ever widening anything, to prove afterwards that it took, and to
refuse rather than adopt a directory that was already open.
§What is admitted, and why that is the minimum
| Trustee | Rights | Why it cannot be dropped |
|---|---|---|
SY — LocalSystem | Full control, inherited | A boot registration runs as LocalSystem and must create, materialize and clean attempt directories |
BA — Administrators | Full control, inherited | 07-security.md already places a local administrator outside this threat model; without it an operator cannot clean up after a service account they are not logged in as |
| the selected account | ADMITTED_RIGHTS, inherited | A login task or a foreground daemon runs as an ordinary user whose token contains neither of the above |
The third row is load-bearing in a way that is easy to miss. A login-mode
registration is a Task Scheduler task rendered with
RunLevel = LeastPrivilege (see crate::service::windows_scheduled_task_xml),
so it runs under the operator’s filtered token — in which the
Administrators group is present but deny-only. A DACL naming only SY and
BA therefore grants such a task nothing at all, even when the operator is
an administrator. The explicit per-account ACE is what makes login mode work,
and it is also why a mode change has to reconcile it: the account admitted
for login mode is not the account boot mode needs.
§Why the account gets modify rather than full control
FA is FILE_ALL_ACCESS, which includes WRITE_DAC and WRITE_OWNER — the
two rights that would let the admitted account undo the protection this
module exists to apply. ADMITTED_RIGHTS is read, write, execute and
delete, which is everything “create a child, materialize a runner into it,
and clean it up again” needs and nothing that can re-open the root. Deleting
a whole attempt tree works because the inherited ACE grants DELETE on every
entry below, which is what remove_dir_all actually requires; the parent’s
FILE_DELETE_CHILD is a convenience this deliberately does not grant.
§Custom roots are read, never rewritten
An operator’s host set-runtime-root path is theirs. This module offers no
public function that applies a security descriptor to a caller-chosen path:
ensure_default_root resolves crate::runner_root::default_runner_root
itself and takes no path at all, and report — the entry point for a
configured custom root — only reads. That is the whole of “custom roots are
never re-ACLed”, enforced by the shape of the API rather than by a check
somebody has to remember to write.
§Everything decidable is decided purely
default_root_sddl, grants_broad_write, admits_exactly and
redact are pure functions over text with no cfg, no privileges and no
filesystem, for the reason this crate gives everywhere else: a Linux CI leg
can assert the exact descriptor a Windows host will write, and the one test
that needs a real DACL is the privileged one that has a real machine.
Structs§
- Root
Access Change - A
RootAccessSummaryplus what it would take to undo.
Enums§
- Admitted
Trustee - One trustee a runner root admits, named without naming an account.
- Reversal
- What undoing a
RootAccessChangeachieved. - Root
Access Error - Why the default runner root could not be created, inspected, or reconciled.
- Root
Access Report - What a runner root’s access control amounts to, said without naming an account.
- Root
Access Summary - What creating or reconciling the default runner root amounted to.
- Root
Admission - Which account, beyond the two constants, the root must admit.
Constants§
- ADMITTED_
RIGHTS - The rights the selected login or foreground account is admitted with.
- INHERITANCE
- The inheritance flags every ACE this module writes carries.
- WRITE_
MASK - The access mask bits that amount to “may change what is in this directory, or who may”.
Functions§
- admits_
exactly - Whether a DACL is already exactly what
default_root_sddlwould write. - default_
root_ sddl - The security descriptor the default runner root is created and reconciled with, in SDDL.
- ensure_
default_ root - Creates or reconciles the platform default runner root.
- grants_
broad_ write - Whether a DACL lets a local user unrelated to this product write inside the object it protects.
- is_
protected - Whether a DACL carries
SE_DACL_PROTECTED, so that nothing is inherited into it from the volume root. - redact
- A security descriptor with account SIDs reduced to the fact that they are account SIDs.
- report
- Describes a runner root’s access control without changing it.
- write_
trustees - Every trustee a DACL grants write access to, canonicalised.