Change:
By default, opening a named pipe on Windows allows the server to impersonate the client. This is a security vulnerability. Pass to prevent this. Since it fixes a security hole, I don’t think this needs an RFC.
Where do we use named pipes?
Nowhere, but it is possible to open a named pipe as a file.
Could you be more clear? What exactly needs to change inside Rust? I assume we'd have to add some form of detection around file opening in windows..?
Whenever libstd calls CreateFileW(), it needs to pass these flags to avoid a local privilege escalation exploit.
can you tell anything about what potential issue you hit when trying to work on this in Or do you have WIP code of the test you where working on?
A simple explanation of the security problem: What could be a problem with setting these flags always: the flag is the same as . The first is supposed to be used with named pipes, the other for files and directories. So if we start to unconditionally add , it will in reality set the in almost all cases. Now I've never seen a system with 'hierarchical storage' where would be necessary. It is intended for systems that combine fast store like hard drives, with slow bulk storage like tapes. File operations like indexing, searching, or backup that want to work well on such systems should open files that have the attribute with this flag. Otherwise a lot of data from tape may be put back online on hard drives. See at The Old New Thing. While investigation this, I found another issue with : one of the values it takes is , whis is simply . Currently, when you set , it will silently be ignored unless you also happen to set (which our API is supposed to set automatically). Easy to fix though. Now I don't care much for working well with hierarchical storage. But we should not break it without having some sort of workaround available. We can say that if user code contains it should be able to handle Windows-specific oddities such as this one. We could make it so that even is enough to disable automatic sqos flags. But it doesn't feel great to just drop a security measure when the user could be doing something unrelated, such as the buffering hint . Only set when we know what we are trying to open is a named pipe. I think all named pipes start with , and we know the filename when setting the flags. But I am not sure if this really works, or if it is possible for an unprivileged process to create a symbolic link to one in the object manager. I don't know if I'll get to making a PR and doing the required testing, just writing down what I've found so far.

Discussion:
/// the specified value (or combines it with `custom_flags` and `attributes` /// to set the `dwFlagsAndAttributes` for [`CreateFile`]). /// <del> /// By default, `security_qos_flags` is set to `SECURITY_ANONYMOUS`. For /// information about possible values, see [Impersonation Levels] on the /// Windows Dev Center site. /// </del> <ins> /// By default `security_qos_flags` is not set. It should be specified when /// opening a named pipe, to control to which degree a server process can /// act on behalf of a client process (security impersonation level). /// /// When `security_qos_flags` is not set a malicious program can gain the /// elevated privileges of a privileged Rust process when it allows opening /// user-specified paths, by tricking it into opening a named pipe. So /// arguably `security_qos_flags` should also be set when opening arbitrary /// paths. However the bits can then conflict with other flags, specifically /// `FILE_FLAG_OPEN_NO_RECALL`. /// /// For information about possible values, see [Impersonation Levels] on the /// Windows Dev Center site. The `SECURITY_SQOS_PRESENT` flag is set /// automatically when using this method. </ins> /// # Examples /// /// ```no_run <ins> /// # #[cfg(for_demonstration_only)] /// extern crate winapi; /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; } </ins> /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; ///

///     .create(true) /// ///     // Sets the flag value to `SecurityIdentification`. <del> ///     .security_qos_flags(1) </del> <ins> ///     .security_qos_flags(winapi::SECURITY_IDENTIFICATION) </ins> /// <del> ///     .open("foo.txt"); </del> <ins> ///     .open(r".pipeMyPipe"); </ins> /// ``` /// /// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx

pub fn access_mode(&mut self, access_mode: u32) { self.access_mode = Some(access_mode); } pub fn share_mode(&mut self, share_mode: u32) { self.share_mode = share_mode; } pub fn attributes(&mut self, attrs: u32) { self.attributes = attrs; } <del> pub fn security_qos_flags(&mut self, flags: u32) { self.security_qos_flags = flags; } </del> <ins> pub fn security_qos_flags(&mut self, flags: u32) { // We have to set `SECURITY_SQOS_PRESENT` here, because one of the valid flags we can // receive is `SECURITY_ANONYMOUS = 0x0`, which we can't check for later on. self.security_qos_flags = flags | c::SECURITY_SQOS_PRESENT; } </ins> pub fn security_attributes(&mut self, attrs: c::LPSECURITY_ATTRIBUTES) { self.security_attributes = attrs as usize; }

self.custom_flags | self.attributes | self.security_qos_flags | <del> if self.security_qos_flags != 0 { c::SECURITY_SQOS_PRESENT } else { 0 } | </del> if self.create_new { c::FILE_FLAG_OPEN_REPARSE_POINT } else { 0 } } }