While working on T235357, I noticed that img_auth.php calls FileBackend::streamFile() with incorrect parameters. Instead of passing the headers as a member of $params, it tries to pass it as a non-existent second parameter. The bug has probably existed since the feature was introduced in 0eb52399689df5fd1401eab951f3a8ef460f7665. The author probably confused the signature with FileRepo::streamFile(), which does take headers as the second parameter.
This occurs only when streaming images from directories that are configured with $wgImgAuthUrlPathMap. I note that in private wikis in WMF production, only EasyTimeline is configured in this way. So in simple terms, for WMF, the risk is that after an authorized user views an EasyTimeline image, it may be cached in ATS, so that an unauthorized user may download the file by requesting the same URL.
The fix was in PS1 of https://gerrit.wikimedia.org/r/c/mediawiki/core/+/584817 , but I backed it out when I realised that it might be treated as a security issue.
I tested the issue locally and confirmed the lack of CC headers, using a simple FSFileBackend to handle a path, not EasyTimeline. I confirmed that the headers are sent with the fix quoted below.
commit 397092d24348e942b54205c0b77ec7b80bbd385a (HEAD -> bug/T235357) Author: Tim Starling <tstarling@wikimedia.org> Date: Tue Mar 31 17:02:49 2020 +1100 Fix accidental public CC headers in img_auth.php Incorrect parameters to FileBackend::streamFile() caused Cache-Control:private and Vary:Cookie response headers to be omitted when requesting a file in a path configured by $wgImgAuthUrlPathMap. Typically this is used to deliver images generated by extensions. Change-Id: I404d9462e4b35d3d832bfab21954ff87e46e3eb2 diff --git a/img_auth.php b/img_auth.php index b3f82018eb..74f9cc2e13 100644 --- a/img_auth.php +++ b/img_auth.php @@ -99,8 +99,10 @@ function wfImageAuthMain() { } if ( $be->fileExists( [ 'src' => $filename ] ) ) { wfDebugLog( 'img_auth', "Streaming `" . $filename . "`." ); - $be->streamFile( [ 'src' => $filename ], - [ 'Cache-Control: private', 'Vary: Cookie' ] ); + $be->streamFile( [ + 'src' => $filename, + 'headers' => [ 'Cache-Control: private', 'Vary: Cookie' ] + ] ); } else { wfForbidden( 'img-auth-accessdenied', 'img-auth-nofile', $path ); }