astrid-runtime/astrid · error

malformed Windows ACL for {description}: {reason}

Error message

malformed Windows ACL for {description}: {reason}

What it means

The bounded ACL parser in acl.rs produces this error whenever a raw Windows ACL structure fails structural validation: null DACL pointer, invalid ACL per IsValidAcl, out-of-bounds ACEs, bad SID lengths, or leftover bytes. It guards against corrupted or maliciously crafted security descriptors returned for the named pipe, converting them into a PermissionDenied error of the form 'malformed Windows ACL for {description}: {reason}' where {reason} details the exact defect.

Source

Thrown at crates/astrid-core/src/local_transport/windows/acl.rs:339

    }

    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_OBJECT_ACE_TYPE;

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

    impl AlignedAce {
        fn with_header(ace_type: u32, ace_size: u16) -> Self {
            let mut result = Self([0; 64]);
            result.0[0] = u8::try_from(ace_type).unwrap();

View on GitHub (pinned to affd8760f4)

Solutions

  1. Retry the connection once — if the descriptor was transiently inconsistent this usually resolves it by re-reading a valid descriptor.
  2. Recreate the pipe via the library so a known-good descriptor is installed.
  3. Check for third-party filter drivers (antivirus/EDR) touching named-pipe security descriptors and exclude the pipe path.
  4. Capture the {reason} text from the message and report it if it persists on pipes you control — it indicates corrupted ACL structures.
Defensive patterns

Strategy: retry

Validate before calling

// Preflight: read the descriptor yourself and run IsValidAcl before connecting
// unsafe { IsValidAcl(dacl_ptr) } == 0 => recreate the pipe before calling connect()

Try / catch

// Malformed ACLs are rarely recoverable in-process; do one bounded retry then surface the reason
for attempt in 0..2 {
    match connect() {
        Err(e) if attempt == 0 && e.to_string().starts_with("malformed Windows ACL") => continue,
        r => break r.map_err(|e| anyhow!("pipe ACL invalid: {e}")),
    }
}

Prevention

When it happens

Trigger: Called from ValidatedAcl::from_raw, ValidatedAcl::ace, parse_ace, expected_sid_length, or bytes_remaining_from when GetSecurityInfo returns an ACL/ACE/SID that fails bounds or structure checks during connect()/accept() pipe validation.

Common situations: Kernel/driver corruption or a buggy third-party filter driver rewriting pipe ACLs; memory corruption or a hostile process tampering with pipe security descriptors; Windows version quirks producing unusual SID sub-authority counts; fuzzed/adversarial pipe endpoints.

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