astrid-runtime/astrid · error

PermissionDenied

PermissionDenied

Error message

trusted Windows parent has an untrusted owner: {description}

What it means

When validating a trusted Windows parent directory, the library first checks that the directory's owner SID is one of the trusted principals (current user, LOCAL_SYSTEM, or Administrators). If the owner is someone else — another account, a service SID, or TrustedInstaller — the directory could be re-ACLed against the current user by its owner, so validation fails with io::ErrorKind::PermissionDenied.

Source

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

        // SAFETY: GetSecurityInfo returned `dacl` inside the descriptor
        // allocation retained by `allocation`.
        unsafe { ValidatedAcl::from_raw(dacl, &allocation, description) }.and_then(|acl| {
            validate_trusted_parent_acl_parts(&required, owner, &acl, dangerous_access, description)
        })
    };
    drop(allocation);
    result
}

fn validate_trusted_parent_acl_parts(
    required: &RequiredSids,
    owner: PSID,
    acl: &ValidatedAcl<'_>,
    dangerous_access: u32,
    description: &str,
) -> io::Result<()> {
    if !required.is_trusted(owner) {
        return Err(io::Error::new(
            io::ErrorKind::PermissionDenied,
            format!("trusted Windows parent has an untrusted owner: {description}"),
        ));
    }

    for index in 0..acl.ace_count() {
        let (flags, mask, sid) = match acl.ace(index)? {
            ValidatedAce::Allow { flags, mask, sid } => (flags, mask, sid),
            ValidatedAce::Deny { .. } => continue,
            ValidatedAce::Unsupported { ace_type, .. } => {
                return Err(io::Error::new(
                    io::ErrorKind::PermissionDenied,
                    format!(
                        "trusted Windows parent has unsupported ACE type {ace_type}: {description}"
                    ),
                ));
            },
        };

View on GitHub (pinned to affd8760f4)

Solutions

  1. Take ownership and reassign to the current user: `takeown /f <parent> /r` then `icacls <parent> /setowner "%USERNAME%" /t` (elevated).
  2. Delete the parent directory and recreate it under the current account so ownership is correct from the start.
  3. Run the application consistently under the same account that created the private root (avoid mixing elevated/admin and normal sessions).
  4. Use a private root inside the per-user profile (e.g. %LOCALAPPDATA%) instead of a shared location owned by another principal.

Example fix

// before: root created by an elevated installer, owned by Administrators
C:\ProgramData\vendor\priv

// after: per-user root owned by the current user
%LOCALAPPDATA%\vendor\priv
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the parent is owned by the current user before use (PowerShell):
// $acl = Get-Acl C:\priv-root
// if ($acl.Owner -ne "$env:USERDOMAIN\$env:USERNAME") {
//   # recreate the folder under this account, or take ownership elevated:
//   # takeown /f C:\priv-root /r ; icacls C:\priv-root /setowner "$env:USERNAME" /t
// }

Prevention

When it happens

Trigger: validate_trusted_parent_acl_parts, invoked through validate_trusted_parent_acl_handle_with_mask during private-directory setup or trusted-parent checks, finds GetSecurityInfo returned an owner SID that RequiredSids::is_trusted rejects.

Common situations: The parent folder was created by an installer running as another account, by the SYSTEM service, or by a different logged-in user; directories created under elevated vs non-elevated shells can end up owned by the Administrators group vs the user, depending on UAC token settings; moving/copying folders can change ownership.

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/dcc74891fd67aeb7. Report an issue: GitHub.