astrid-runtime/astrid · error

PermissionDenied

PermissionDenied

Error message

malformed Windows ACL for {description}: {reason}

What it means

This error is produced by the malformed() helper in the Windows ACE parser whenever a raw ACE from the OS cannot be decoded safely: wrong length, invalid SID, truncated structure, or an unexpected SID length for the ACE type. It signals a corrupt or hostile security descriptor rather than a policy violation, so it is surfaced as PermissionDenied.

Source

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

    let subauthority_bytes = usize::from(fixed_header[1])
        .checked_mul(SID_SUBAUTHORITY_SIZE)
        .ok_or_else(|| malformed(description, "the ACE SID length overflowed"))?;
    let expected_length = SID_FIXED_HEADER_SIZE
        .checked_add(subauthority_bytes)
        .ok_or_else(|| malformed(description, "the ACE SID length overflowed"))?;
    if expected_length > sid_capacity {
        return Err(malformed(
            description,
            "an access-allowed ACE contains subauthorities beyond its declared size",
        ));
    }

    Ok(expected_length)
}

fn malformed(description: &str, reason: &str) -> io::Error {
    io::Error::new(
        io::ErrorKind::PermissionDenied,
        format!("malformed Windows ACL for {description}: {reason}"),
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use windows_sys::Win32::Security::ACL_REVISION;
    use windows_sys::Win32::System::SystemServices::{
        ACCESS_ALLOWED_CALLBACK_ACE_TYPE, ACCESS_ALLOWED_OBJECT_ACE_TYPE,
    };

    #[repr(align(4))]
    struct AlignedAce([u8; 64]);

    impl AlignedAce {
        fn with_header(ace_type: u32, ace_size: u16) -> Self {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Read the descriptor again (the corruption may be transient) with icacls <path> or Get-Acl to see what the OS reports
  2. Restore the ACL: icacls <path> /reset or reinstall/rewrite the file so a fresh descriptor is created
  3. Run chkdsk on the volume if descriptors are repeatedly malformed
  4. If a specific filter/filesystem driver is in the path, exclude the file from it or report the bug to the driver vendor
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity-check the descriptor before full validation
fn descriptor_readable(path: &std::ffi::OsStr) -> bool {
    std::fs::metadata(path).is_ok() // plus a GetNamedSecurityInfoW probe that succeeds
}

Try / catch

match validate_trusted_file_acl_handle(&file) {
    Err(e) if e.to_string().starts_with("malformed Windows ACL") => {
        eprintln!("Corrupt security descriptor; reset ACL or reinstall the file");
    }
    other => other?,
}

Prevention

When it happens

Trigger: parse_ace/from_raw reading an ACE header whose declared length does not match the buffer, an SID whose expected_sid_length disagrees with the actual sub-authority count, or any structurally invalid ACE while decoding a file's DACL.

Common situations: Corrupted NTFS security descriptors after disk issues; third-party filesystems or filter drivers returning non-standard ACE layouts; fuzzed or crafted descriptors; buffers truncated by an intermediate API layer.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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