Skip to main content
CybersecurityVulnerability Management

Windows Named Pipes Expose Security Risks

Administrator typing on laptop in office with server equipment blurred in background.

When a privileged Windows service accepts commands via a named pipe, that pipe can become an API to privileged capabilities — and therefore a security boundary that must be defended. Farid Mustafayev, a cybersecurity expert at ThreatLocker, lays out why a local interprocess channel is not the same as a trusted one and how architects should redesign pipes to avoid privilege escalation, confused-deputy errors, and denial-of-service.

Local does not mean trusted: identity and access control

Named pipes are convenient because they are fast and built into Windows, but Mustafayev stresses that "local" does not equal "private." A workstation may run processes under LocalSystem, administrators, standard users, service accounts, and separate interactive or remote sessions — and any process that knows the pipe name and has sufficient rights can attempt to connect. The server must therefore use an explicit security descriptor (DACL) instead of relying on default permissions or broad groups such as Everyone or Authenticated Users.

Connection permission is only the first step: authentication determines who connected; authorization determines what that identity may do. The article recommends separating the two, applying command-level authorization so that a client allowed to query status cannot, for example, stop services, change protected settings, or write arbitrary registry keys.

Verify endpoints and treat multiple identity checks as defense in depth

Mustafayev outlines concrete verification techniques: call GetNamedPipeClientProcessId or GetNamedPipeServerProcessId after connection, use QueryFullProcessImageName to check the executable path, and validate Authenticode signatures via WinVerifyTrust. But he warns these are secondary controls — PIDs can be spoofed and handles transferred — so strong decisions must be based on Windows security identities (SIDs), logon sessions, and a restrictive pipe DACL.

The pipe name itself is not a secret. An attacker can create a pipe with the expected name before the legitimate server starts; the first-pipe-instance option may detect this but cannot replace proper access controls or server identity verification.

Impersonation, privileged operations, and the confused-deputy problem

Named-pipe impersonation can be useful: .NET’s NamedPipeServerStream.RunAsClient and native APIs such as ImpersonateNamedPipeClient / RevertToSelf allow the server to perform checks and operations under the client's token. Mustafayev emphasizes strict rules: impersonate only for actions that must use the client’s permissions, keep the impersonation scope minimal, check that impersonation succeeded, and always revert in a finally block. If impersonation fails, the request must fail closed rather than silently executing under the server’s privileged identity.

Equally important is narrowing privileged commands. The article contrasts dangerous general-purpose operations (WriteFile(path, content); StartProcess(path, arguments)) with narrowly defined requests (UpdateApplicationConfiguration; InstallApprovedUpdate). Broad commands create a larger attack surface and transform the service into a confused deputy that performs attacker-chosen privileged work.

Messages are untrusted: framing, validation, and availability

Every pipe message must be treated as untrusted input. The recommended protocol uses explicit framing (version, command, payload length) and enforces a maximum payload (example MaxMessageSize = 1024 * 1024). Servers must reject invalid lengths before allocating memory, validate paths via Path.GetFullPath and allowlists, and guard against symbolic links, junctions, and time-of-check/time-of-use races.

Availability protections belong in the same model: bound simultaneous connections and pipe instances, timeouts, cancellation, bounded concurrency, per-client rate limits, and limits on pending requests. Named-pipe buffers consume kernel nonpaged pool, and excessive instances or large buffers can contribute to resource exhaustion. Windows pipes can also be remotely accessible in some configurations; to guarantee local-only communication, use PIPE_REJECT_REMOTE_CLIENTS at creation and deny NT AUTHORITY\NETWORK in the pipe ACL.

What this means for developers, security teams, and enterprise IT

  • Developers: restrict the pipe DACL, keep the protocol narrow and versioned, validate framing and payloads, authorize every command, and isolate parsing from privileged execution.
  • Security teams: log rejected connections, failed identity checks, malformed messages, and unauthorized commands; apply audit trails that include user, session, peer PID, and command type while avoiding logging secrets.
  • Enterprise IT: configure services to reject remote clients when local-only IPC is intended and deny NT AUTHORITY\NETWORK in pipe ACLs; enforce short timeouts and global connection limits to mitigate DoS.

Mustafayev’s central principle is succinct: a named pipe should expose the smallest possible interface between trust levels. Combine restrictive access control, endpoint verification, operation-level authorization, strict input validation, bounded resource usage, and narrowly scoped privileged functionality — and fail closed when any verification cannot be completed. That combination, he writes, prevents a pipe from becoming an unintended API to privileged system capabilities.

Read the original ThreatLocker analysis on BleepingComputer