astrid-runtime/astrid · error
named-pipe DACL contains a non-canonical access entry
Error message
named-pipe DACL contains a non-canonical access entry
What it means
While walking the pipe's DACL, each ACE must be an ACCESS_ALLOWED_ACE; anything else (deny ACE, audit ACE, unsupported type) fails this check in validate_pipe_security. The library only recognizes a canonical allow-only ACL, so non-allow entries indicate a foreign or tampered ACL and the connection is refused with PermissionDenied.
Source
Thrown at crates/astrid-core/src/local_transport/windows.rs:953
dacl,
&descriptor_allocation,
"named-pipe security descriptor",
)
}?;
let expected_aces = if current.equals(&system) { 1 } else { 2 };
let ace_count = dacl.ace_count();
if ace_count != expected_aces {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!("named-pipe DACL has {ace_count} entries; expected exactly {expected_aces}"),
));
}
let mut saw_current = false;
let mut saw_system = current.equals(&system);
for index in 0..ace_count {
let ValidatedAce::Allow { flags, mask, sid } = dacl.ace(index)? else {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"named-pipe DACL contains a non-canonical access entry",
));
};
if flags != 0 || !is_canonical_pipe_full_control(mask) {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"named-pipe DACL contains a non-canonical access entry",
));
}
if unsafe { EqualSid(sid.as_ptr(), current.as_psid()) } != 0 && !saw_current {
saw_current = true;
} else if unsafe { EqualSid(sid.as_ptr(), system.as_psid()) } != 0 && !saw_system {
saw_system = true;
} else {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
"named-pipe DACL grants an unexpected or duplicate principal",View on GitHub (pinned to affd8760f4)
Solutions
- Recreate the pipe via this library so its DACL contains only access-allowed ACEs for the current user and Local System.
- Remove the deny/audit ACEs from the pipe's ACL (`Get-Acl` / `Set-Acl` or icacls) in the creating process.
- Identify the tool injecting extra ACEs (antivirus, EDR, GPO) and exclude the pipe path from that policy.
- Choose a fresh pipe name not covered by existing ACL policy.
Example fix
// before: adding a deny ACE for another user AddAccessDeniedAceEx(dacl, ..., &other_user_sid); // after: keep the DACL allow-only; rely on it granting ONLY current user + SYSTEM AddAccessAllowedAceEx(dacl, ..., GENERIC_ALL, ¤t_user_sid);
Defensive patterns
Strategy: validation
Validate before calling
// PowerShell preflight: no Deny rules on the pipe
// if ((Get-Acl \\.\pipe\myapp).Access | Where-Object AccessControlType -eq 'Deny') { 'non-canonical ACE present' } Try / catch
match connect() {
Err(e) if e.to_string().contains("non-canonical access entry") => {
eprintln!("pipe ACL contains deny/audit ACEs; recreate the pipe via this library");
}
r => r?,
} Prevention
- Keep the pipe DACL allow-only; never add Deny or audit ACEs
- Check antivirus/EDR tools that harden named-pipe ACLs and exclude your pipe path
- Recreate the pipe through the library instead of hand-editing ACLs
- Validate the ACL with Get-Acl after any security-policy change
When it happens
Trigger: connect()/accept() where dacl.ace(index) parses an ACE whose type is not access-allowed, e.g. an ACCESS_DENIED_ACE or SYSTEM_AUDIT_ACE present in the pipe DACL.
Common situations: Hardening tooling or group policy added deny/audit ACEs to the pipe; an admin explicitly denied another account and added a deny entry; the pipe was created by different software with a richer ACL.
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
- named-pipe has a null or missing DACL
- named-pipe DACL has {ace_count} entries; expected exactly {e
- named-pipe DACL grants an unexpected or duplicate principal
- named-pipe DACL omits the current user or Local System
- named-pipe DACL control is not explicit and protected (contr
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/072b019cbcbb6d84.
Report an issue: GitHub.