Description
On Unix, when you create a NamedPipeServerStream with PipeOptions.CurrentUserOnly, the underlying Unix domain socket file is now created with file permissions 0600 (read/write for the owning user only). Previously, the socket file inherited permissions from the process umask (typically 0644 or 0755), and CurrentUserOnly only restricted who could connect - it did not restrict who could see or open the socket file on disk.
What this means for you:
- Other local users on the same machine can no longer open or
connect() to the socket file at the OS level when the server is created with CurrentUserOnly. This matches the documented intent of the option and aligns Unix behavior with Windows.
- If your application relied on a non-owner user being able to reach a
CurrentUserOnly server's socket file (for example, a helper process running under a different account, or external tooling that probes the socket), those connections will now fail with a permission error.
- Within a single process, if multiple
NamedPipeServerStream instances share the same path, the socket's mode is ratcheted: as soon as any instance for that path is created with CurrentUserOnly, the file is tightened to 0600 and stays 0600 for the rest of that shared server's lifetime, even after the CurrentUserOnly instance is disposed and even if later instances for the same path do not pass CurrentUserOnly. The mode is never loosened back.
See dotnet/runtime#127239.
Version
.NET 11 Preview 4
Previous behavior
On Unix, the socket file backing a NamedPipeServerStream was created with whatever permissions the process umask allowed (commonly 0644 or 0755). PipeOptions.CurrentUserOnly did not change the on-disk file mode:
using var server = new NamedPipeServerStream(
"/tmp/mypipe", PipeDirection.InOut, 1,
PipeTransmissionMode.Byte, PipeOptions.CurrentUserOnly);
// Mode reflected umask, e.g. UserRead | UserWrite | GroupRead | OtherRead
UnixFileMode mode = File.GetUnixFileMode("/tmp/mypipe");
Other local users could stat and attempt to connect() to the socket. Cross-user connection attempts were rejected at connect time by CurrentUserOnly peer-credential checks, but the socket file itself was world-visible and connectable from a permissions standpoint.
New behavior
When PipeOptions.CurrentUserOnly is specified, the socket file is chmod'd to 0600 immediately after bind():
using var server = new NamedPipeServerStream(
"/tmp/mypipe", PipeDirection.InOut, 1,
PipeTransmissionMode.Byte, PipeOptions.CurrentUserOnly);
// Always UserRead | UserWrite (0600)
UnixFileMode mode = File.GetUnixFileMode("/tmp/mypipe");
Other local users (other than root) can no longer open or connect() to the socket file at the OS level.
For the in-process SharedServer cache (multiple NamedPipeServerStream instances using the same path), the mode change is one-way:
- If a non-
CurrentUserOnly instance is created first and a later instance for the same path requests CurrentUserOnly, the file mode is tightened to 0600 at that point and stays 0600 for the remainder of the path's shared lifetime.
- A later non-
CurrentUserOnly instance does not loosen a mode that a previous CurrentUserOnly instance tightened.
Type of breaking change
Reason for change
PipeOptions.CurrentUserOnly was documented as restricting access to the current user, but on Unix the underlying socket file was created with permissions derived from the process umask. Enforcement relied solely on peer-credential checks at connect time, which left the socket file discoverable and openable by other local users and made the behavior inconsistent with the option's documented intent and with the Windows implementation. Hardening the file mode aligns the on-disk permissions with the documented guarantee.
Recommended action
Most callers benefit from the tighter permissions and require no action.
If you have code or tooling that depends on the socket file being readable or connectable by other local users (for example, a non-current-user client connecting to the same path), do the following:
- Stop passing
PipeOptions.CurrentUserOnly when the server is intended to be reachable by users other than the owner.
Be aware of the in-process ratcheting behavior: if any NamedPipeServerStream for a given path in the process specifies CurrentUserOnly, all subsequent instances for that path will see 0600 permissions on the socket file until the shared server entry is released.
Feature area
Core .NET libraries
Affected APIs
System.IO.Pipes.NamedPipeServerStream constructors that accept a PipeOptions parameter, when PipeOptions.CurrentUserOnly is specified, on Unix platforms.
Associated WorkItem - 572080
Description
On Unix, when you create a
NamedPipeServerStreamwithPipeOptions.CurrentUserOnly, the underlying Unix domain socket file is now created with file permissions0600(read/write for the owning user only). Previously, the socket file inherited permissions from the process umask (typically0644or0755), andCurrentUserOnlyonly restricted who could connect - it did not restrict who could see or open the socket file on disk.What this means for you:
connect()to the socket file at the OS level when the server is created withCurrentUserOnly. This matches the documented intent of the option and aligns Unix behavior with Windows.CurrentUserOnlyserver's socket file (for example, a helper process running under a different account, or external tooling that probes the socket), those connections will now fail with a permission error.NamedPipeServerStreaminstances share the same path, the socket's mode is ratcheted: as soon as any instance for that path is created withCurrentUserOnly, the file is tightened to0600and stays0600for the rest of that shared server's lifetime, even after theCurrentUserOnlyinstance is disposed and even if later instances for the same path do not passCurrentUserOnly. The mode is never loosened back.See dotnet/runtime#127239.
Version
.NET 11 Preview 4
Previous behavior
On Unix, the socket file backing a
NamedPipeServerStreamwas created with whatever permissions the process umask allowed (commonly0644or0755).PipeOptions.CurrentUserOnlydid not change the on-disk file mode:Other local users could
statand attempt toconnect()to the socket. Cross-user connection attempts were rejected at connect time byCurrentUserOnlypeer-credential checks, but the socket file itself was world-visible and connectable from a permissions standpoint.New behavior
When
PipeOptions.CurrentUserOnlyis specified, the socket file ischmod'd to0600immediately afterbind():Other local users (other than root) can no longer open or
connect()to the socket file at the OS level.For the in-process
SharedServercache (multipleNamedPipeServerStreaminstances using the same path), the mode change is one-way:CurrentUserOnlyinstance is created first and a later instance for the same path requestsCurrentUserOnly, the file mode is tightened to0600at that point and stays0600for the remainder of the path's shared lifetime.CurrentUserOnlyinstance does not loosen a mode that a previousCurrentUserOnlyinstance tightened.Type of breaking change
Reason for change
PipeOptions.CurrentUserOnlywas documented as restricting access to the current user, but on Unix the underlying socket file was created with permissions derived from the process umask. Enforcement relied solely on peer-credential checks at connect time, which left the socket file discoverable and openable by other local users and made the behavior inconsistent with the option's documented intent and with the Windows implementation. Hardening the file mode aligns the on-disk permissions with the documented guarantee.Recommended action
Most callers benefit from the tighter permissions and require no action.
If you have code or tooling that depends on the socket file being readable or connectable by other local users (for example, a non-current-user client connecting to the same path), do the following:
PipeOptions.CurrentUserOnlywhen the server is intended to be reachable by users other than the owner.Be aware of the in-process ratcheting behavior: if any
NamedPipeServerStreamfor a given path in the process specifiesCurrentUserOnly, all subsequent instances for that path will see0600permissions on the socket file until the shared server entry is released.Feature area
Core .NET libraries
Affected APIs
System.IO.Pipes.NamedPipeServerStreamconstructors that accept aPipeOptionsparameter, whenPipeOptions.CurrentUserOnlyis specified, on Unix platforms.Associated WorkItem - 572080