astrid-runtime/astrid · error

private Windows path ACL is not restricted to the current us

Error message

private Windows path ACL is not restricted to the current user and required system principals: {description}

What it means

After reading the DACL of a private Windows path or handle, the library compares every ACE against its expectation: the ACL must be protected, have a user-owner allow entry, and be restricted to exactly the current user plus the required system principals (LOCAL_SYSTEM, Administrators). If acl_rules_are_private determines the ACL deviates — extra grantees, missing entries, unprotected/inherited ACL, wrong access bits — it raises io::ErrorKind::PermissionDenied.

Source

Thrown at crates/astrid-core/src/platform_fs/windows/acl.rs:538

) -> io::Result<()> {
    let mut control = 0_u16;
    let mut revision = 0_u32;
    // SAFETY: `descriptor` is the live descriptor returned above and both
    // output pointers are valid.
    if unsafe { GetSecurityDescriptorControl(descriptor, &raw mut control, &raw mut revision) } == 0
    {
        return Err(io::Error::last_os_error());
    }
    let dacl_is_protected = control & SE_DACL_PROTECTED != 0;
    let owner_is_allowed = required.classify(owner) != AclPrincipal::Other;

    let mut rules = Vec::with_capacity(usize::try_from(acl.ace_count()).unwrap_or_default());
    for index in 0..acl.ace_count() {
        rules.push(private_acl_rule(required, acl.ace(index)?, is_directory));
    }

    if !acl_rules_are_private(is_directory, dacl_is_protected, owner_is_allowed, &rules) {
        return Err(io::Error::new(
            io::ErrorKind::PermissionDenied,
            format!(
                "private Windows path ACL is not restricted to the current user and required system principals: {description}"
            ),
        ));
    }
    Ok(())
}

fn private_acl_rule(required: &RequiredSids, ace: ValidatedAce<'_>, is_directory: bool) -> AclRule {
    let invalid = || AclRule {
        principal: AclPrincipal::Other,
        access: AclAccess::Other,
        inheritance: AclInheritance::InheritedOrOther,
    };
    let ValidatedAce::Allow { flags, mask, sid } = ace else {
        return invalid();
    };

View on GitHub (pinned to affd8760f4)

Solutions

  1. Delete the private directory/file and recreate it via the library so it receives the canonical protected ACL.
  2. Fix the ACL to the expected shape: `icacls <path> /inheritance:r /grant:r "%USERNAME%":F /grant:r SYSTEM:F /grant:r Administrators:F`.
  3. Audit group policy / folder-redirection settings that apply inherited ACLs to the temp location; relocate private dirs to a location not governed by those policies.
  4. Identify and exclude the tool (backup, AV, sync client) that modifies the ACL.

Example fix

// before: private dir exposed to a group
// icacls C:\priv /grant Users:F  (breaks validation)

// after: restore the restricted ACL
// icacls C:\priv /inheritance:r /grant:r "%USERNAME%":F /grant:r SYSTEM:F /grant:r Administrators:F
Defensive patterns

Strategy: validation

Validate before calling

// Verify expected grantees before use (PowerShell):
// $acl = Get-Acl C:\priv
// $names = $acl.Access | ForEach-Object { $_.IdentityReference.Value }
// if ($names -notmatch '^(<USER>|NT AUTHORITY\\SYSTEM|BUILTIN\\Administrators)$') {
//   Reset-Acl C:\priv
// }

Prevention

When it happens

Trigger: validate_private_acl or validate_private_acl_handle finds the ACL of a private directory/file does not match the expected shape: another user or group was granted access, inheritance was re-enabled (SE_DACL_PROTECTED cleared), or an allow rule grants more access than the template.

Common situations: Admins or scripts ran `icacls /grant` or `/inheritance:e` on the private temp folder; corporate GPO security policies apply inherited ACLs to temp directories; antivirus/quarantine tools rewrote the ACL; the folder was shared over the network, adding Everyone access.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/358cb89b4fc65847. Report an issue: GitHub.