What does the FOF_NOCOPYSECURITYATTRIBS flag really do (or not do)?


In the old days, the shell copy engine didn't pay attention to ACLs. It just let the file system do whatever the default file system behavior was. The result was something like this:

  • If you copied a file, it opened the destination, wrote to it, and that was it. Result: The copied file has the security attributes of destination (specifically, picking up the inheritable attributes from the container).
  • If you moved a file within the same drive, it moved the file with MoveFile, and that was it. Result: The file retained its security attributes.
  • If you moved a file between drives, then it was treated as a copy/delete. Result: The moved file has the security attributes of the destination (specifically, picking up the inheritable attributes from the container).

Perfectly logical, right? If a new file is created, then the security attributes are inherited from the container. If an existing file is moved, then its security attributes move with it. And since moving a file across drives was handled as a copy/delete, moving a file across drives behaved like a copy.

Users, however, found this behavior confusing. For example, they would take a file from a private folder like their My Documents folder, and move it to a public location like Common Documents, and... the file would still be private.

The FOF_NO­COPY­SECURITY­ATTRIBS flag was introduced in Windows 2000 to address this confusion. If you pass this flag, then when you move a file, even within a drive, the security attributes of the moved file will match the destination directory. (The way the shell implements this flag, by the way, is to move the file like normal, and then reset the security attributes to match the destination. So even though it sounds like a flag that says "don't do X" would be less work than doing X, it's actually more work, because we actually do X+Y and then undo the X part. But it's still far cheaper than copying the file and deleting the original.)

Note that omitting the FOF_NO­COPY­SECURITY­ATTRIBS flag does not mean "Always copy security attributes." If you don't pass the flag, then the security attributes follow the default file system behavior, which sometimes transfers the security attributes and sometimes doesn't. In retrospect, the flag might have been better-named something like FOF_SET­SECURITY­ATTRIBS­TO­MATCH­DESTINATION.

Now the question is how to summarize all this information in the MSDN documentation for the FOF_NO­COPY­SECURITY­ATTRIBS flag? After receiving this explanation of how the flag works, one customer suggested that the text be changed to read "Do not copy the security attributes of the moved file. The destination file receives the security attributes of its new folder. Note that this flag has no effect on copied files, which will always receive the security attributes of the new folder."

But this proposed version actually can be misinterpreted. Everything starting with "Note that" is intended to be guidance. It isn't actually part of the specification; rather, it's sort of "thinking out loud", taking the actual specification and calling out some of its consequences. But how many people reading the above proposed text would fail to realize that the first two sentences are normative but the third sentence is interpretive? In particular, the interpretation says that the copied file will "always" receive the security attributes of the new folder. Is that really true? Maybe in the future there will be a new flag like COPY_FILE_INCLUDE_SECURITY_ATTRIBUTES, and now the "always" isn't so "always" any more.

Anyway, now that you know what the FOF_NO­COPY­SECURITY­ATTRIBS flag does (and doesn't do), maybe you can answer this customer's question:

Download a file via Internet Explorer and put it on the desktop. The file will be marked as having come from the Internet Zone.

Now copy the file with the FOF_NO­COPY­SECURITY­ATTRIBS to some other location.

The resulting file is still marked as Internet Zone. I expected that FOF_NO­COPY­SECURITY­ATTRIBS would remove the Internet Zone security information. Is this a bug in SHFileOperation?

(This article provides enough information for you to explain why the Internet Zone marker is not removed. The answer to the other half of the customer's question—actually removing the marker—lies in this COM method.)

Comments (16)
  1. Marquess says:

    Internet Zone security information is not part of the ACL.

    Should have named it FOF_SET­ACLS­TO­MATCH­DESTINATION.

    ["Security attributes" has a specific meaning, and the Internet Zone information is not part of it. Neither are digital signatures. Or password-protection on ZIP files. Or the words "TOP SECRET" at the top of your Word document. -Raymond]
  2. Bukesros says:

    The zone identifier is stored in an alternate data stream (ADS) that is not part of the ACL.  The ADS is copied along with the $DATA stream (provided that the destination volume supports ADS).

  3. Kyle says:

    @Marquess & @Bukesros

    While you both are right, it's named "FOF_NO­COPY­SECURITY­ATTRIBS", which implies application to all "security attributes" not just the ACL.  Certainly internet zone info is stored in an alternate data stream, but this could be considered a security "attribute" as well.  The suggested name that Marquess provides is a good one, but since it's already in the wild, it's too late.

  4. rs says:

    "Users, however, found this behavior confusing."

    It is. IMO it is not intuitve that the folder structure is hierarchical but security attributes aren't.

  5. mikeb says:

    > Everything starting with "Note that" is intended to be guidance. It isn't actually part of the specification; <<

    That's something I would not have guessed. Count me as one of those who would fail to realize that the 1st 2 sentences are normative and the last interpretive.  However, I also wouldn't necessarily consider things broken if a new flag were added to override the 3rd sentence, but I guess you'd have no shortage of people who would (and maybe applications that needed compatibility shims).

  6. Gabe says:

    mikeb: Note that you would need compatibility shims no matter what the documentation said.

  7. Nick says:

    This seems like a good example of how end users ("normal people") and developers ("technical people") can think so completely different about something relatively simple.  I would never view the little zone marker agreement between IE and the Shell (and now most other browsers) as a security attribute.  It's just metadata that's been somewhat arbitrarily tied to a file.  However, when I stop and think about it, I suppose I could almost see it as related to file security… almost.

    As far as FOF_NO­COPY­SECURITY­ATTRIBS entry on MSDN, you might just link to your blog entry.  Sure, sure, I know this isn't official information of any kind, but from this point forward, if you Google (or Bing, if you lean that way) FOF_NO­COPY­SECURITY­ATTRIBS, your blog post will be the first result. Honestly, this is probably a good thing :)

  8. DWalker59 says:

    It *seems* like the Internet Zone marking should be a security attribute, but … oh well.

    [It's not a security attribute from the file system's point of view, which is the point of view relevant here. In the same way digital signatures are not a security attribute from the file system's point of view either. -Raymond]
  9. Phil Fultz says:

    SECURITY_ATTRIBUTES (msdn.microsoft.com/…/aa379560%28VS.85%29.aspx) is clearly defined, and has been an integral part of the Windows API for two decades.  Of issue is the fact that the SECURITY_ATTRIBUTES type includes the security descriptor and a BOOL indicating if the HANDLE is inheritable.  The latter is not at all applicable to FOF_NO­COPY­SECURITY­ATTRIBS.

    That leaves us the PSECURITY_DESCRIPTOR.  So, as FOF_NO­COPY­SECURITY­ATTRIBS might be better named FOF_NO­COPY­SECURITY­DESCRIPTOR.  

    On the other hand, it is a bit besides the point.  If one's ignorance of the Windows API leads one to believe that the Internet Zone marking is part included as part of the Security Attributes, one might also believe that it is included as part of the Security Descriptor.

    [I agree that FOF_NO­COPY­SECURITY­DESCRIPTOR would have been a better name. Let's see if Microsoft Research ever comes through with that time machine. -Raymond]
  10. Gabe says:

    I agree with Phil that FOF_NO­COPY­SECURITY­DESCRIPTOR is a better name. The term "security descriptor" is very well-defined and should be understood unambiguously by any experienced Windows developer in any context (it even has a Wikipedia entry).

    The term "security attributes" is more generic. In regular Win32 programming it applies to a handle (not a file or folder). In the context of the shell one could easily assume that security attributes include the zone information. After all, the properties page (a shell UI) for a file downloaded from the Internet will have, right under "Attributes", the word "Security" is used to refer to the Internet zone.

    Of course you could argue that Internet Explorer isn't part of the Shell, or that the property page didn't work like that 10-12 years ago when they were creating this option. Regardless, MSDN can be changed at any time, and should use the unambiguous term "security descriptor".

  11. Neil says:

    Does FOF_NO­COPY­SECURITY­ATTRIBS take care of the case where the destination folder has no inheritable ACL entries? (Copying a file to such a folder gives it a default ACL giving you and SYSTEM full control.)

  12. yuhong2 says:

    [I agree that FOF_NO­COPY­SECURITY­DESCRIPTOR would have been a better name. Let's see if Microsoft Research ever comes through with that time machine. -Raymond]

    No need for one. Adding a new constant with the same value do not break compatibility at all.

    [Adding new names for existing constants fell out of favor back in the late 1990's. -Raymond]
  13. 640k says:

    [Adding new names for existing constants fell out of favor back in the late 1990's. -Raymond]

    .h-files fell out of favor back in the late 1990's.

    ["… fell out of favor in Win32 …" Don't make me bring back the nitpicker's corner. -Raymond]
  14. 640k says:

    Win32's use of .h-files suck. For example, h-files should be used to mitigate transitions and to help where the compiler's type system is insufficient. But win32 doesn't use h-files this way. Win32's h-files are useless. As a developer you can hard code everything anyway, because ms are afraid of changing h-files because some noob developers didn't use them back in the 90's. Why are current developers punished becuase some noob developers hard coded stuff in the 90's?

  15. Marquess says:

    .h-files are there to stay for Win32 development, because everyone relies on them (and for good reason). If you don't like .h-files, you can use what Microsoft provided when they decided to start over:

    .Net

  16. Medinoc says:

    What's the deal with .h files? What bugs me more is the *lack* of them when people distribute COM components; one has to jump through hoops to get a .h file from the type library, which makes using said COM components from C (or C++ under IDEs that don't support #import) a pain in the rear.

Comments are closed.