Problem/Motivation
File validation is omitted by uploading file with "php|pl|py|cgi|asp|js", extensions. For example, a form with file field where allowed extensions is set to "doc xlsx", you would assume no other file type can be uploaded. But a user can upload all files with ""php|pl|py|cgi|asp|js" extensions.
This happens because in _file_save_upload_single() files with those dangerous extensions are renamed to have the .txt extension and .txt is added to the list of allowed extensions. This behaviour is surprising when "txt" has been specifically omitted from the list of allowed extensions.
Proposed resolution
Change logic to only rename if .txt is an allowed extension. If txt is not an allowed extension do not allow the file to be uploaded.
Remaining tasks
UX review.- Final code reviews/RTBC.
- Commit.
User interface changes
1. Do not allow uploads of files with dangerous file extensions if txt is not an allowed extension. In this case, end-users would see:
The file %filename could not be uploaded because the extension is insecure.
If txt is an allowed extension, end-users would continue to see (as they have for years):
For security reasons, your upload has been renamed to %filename.
2. Changes to the file field settings page when configuring allowed extensions to detect if "insecure" extensions are being allowed without .txt and throwing an error message about it. This is the "This is mandated when configuring file fields through the user interface." part of the release note snippet below. In this case, site builder admins would see:
The extension %extension is insecure. In order to allow files with this extension to be uploaded add the %txt_extension extension as well.
(where %txt_extension is an untranslatable "txt").
API changes
None
Data model changes
None
Release notes snippet
If you limit allowed extensions and want dangerous files to be uploaded and renamed, you must explicitly allow txt file uploads. This is mandated when configuring file fields through the user interface.
| Comment | File | Size | Author |
|---|---|---|---|
| #84 | 2863652-9.2.x-84.patch | 23.5 KB | dww |
| #83 | 2863652-9.2.x-83.patch | 23.62 KB | alexpott |
Comments
Comment #2
javi.pl commentedComment #3
cilefen commentedI hope this title is clearer.
Comment #4
netlooker commentedWhy those lines are commented?
Comment #5
cilefen commentedComment #6
javi.pl commentedClean up unnecessary comments.
Comment #7
zaporylieAfter uploading a patch you must change issue status to Needs review so Drupal I can apply it and run tests.
Comment #8
zaporylieComment #11
alexpottThis is present in Drupal 8 too afaics and so will need to be fixed there first. It's also present in Drupal 6 so it might be worth searching the issue queue for prior discussions of this issue.
Comment #12
zaporylieTest-only patch. This is supposed to fail.
Comment #14
javi.pl commentedComment #15
moinak_dutta commentedPlease test & review the following patch hopefully it'll solve the problem.
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index a6fc3f6..cb95687 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -813,15 +813,18 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL
// filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
// evaluates to TRUE.
if (!\Drupal::config('system.file')->get('allow_insecure_uploads') && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->getFilename()) && (substr($file->getFilename(), -4) != '.txt')) {
- $file->setMimeType('text/plain');
- // The destination filename will also later be used to create the URI.
- $file->setFilename($file->getFilename() . '.txt');
- // The .txt extension may not be in the allowed list of extensions. We have
- // to add it here or else the file upload will fail.
- if (!empty($extensions)) {
- $validators['file_validate_extensions'][0] .= ' txt';
- drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()]));
- }
+ //check whether file extension contains txt or not
+ if (strpos($validators['file_validate_extensions'][0], 'txt') !== false) {
+ $file->setMimeType('text/plain');
+ // The destination filename will also later be used to create the URI.
+ $file->setFilename($file->getFilename() . '.txt');
+ // The .txt extension may not be in the allowed list of extensions. We have
+ // to add it here or else the file upload will fail.
+ if (!empty($extensions)) {
+ $validators['file_validate_extensions'][0] .= ' txt';
+ drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()]));
+ }
+ }
}
// If the destination is not provided, use the temporary directory.
Comment #17
moinak_dutta commentedComment #20
iampumaI have edited the latest patch and changed the inline comment. Also replaced the array with another variable that is available throughout the function.
I would raise the discussion though if this is a user friendly implementation?
Scenario of a user:
- I allow the extensions 'php js' (or not)
- Now I am able to upload a .php file
- The file is renamed to .txt (although not allowed either)
Scenario of a user (with patch):
- I allow the extensions 'php js'
- Now I am still NOT able to upload a .php file
- I add the extension 'txt'
- Now I am able to upload the .php file, but my .php file is renamed to .txt
As seen above, both scenarios are not optimal. As it both does not restrict what has been set by the user.
Possible solutions:
1: Add a description to the upload file field, that .txt needs to be required due to security purposes in case unsafe extensions are detected?
2: Add an option to the upload file field that allows unsafe file uploads?
3: ?
Comment #23
a.dmitriiev commentedLast patch, re-rolled for 8.6.3
Comment #24
alexpottThe fix here is not quite right because the rename takes place even if the field does allow .php files if you have not allowed insecure uploads. So we need to fix and test for that.
We need to address #20
Comment #25
alexpottHere's a rewrite of the patch to account for #24. Still need to account for the usability considerations. I.e we should warn people to have php without txt in the file config form if insecure uploads are not allowed.
Comment #26
alexpottSo still to do - add an update path to detect a file field which allows potentially a malicious extensions but not txt. We need to add txt for them.
And we need to do the UI stuff.
Comment #27
panchoIs there any usecase for allowing insecure file extensions such as
.phpwhile disallowing insecure uploads but then not allowing them to be renamed to.txteither? I think not.So if insecure uploads are disallowed, we might want to automatically (though probably not silently) add
.txtto the list of allowed extensions, or probably better, let automatically renamed files pass the allowed extensions test. Finally, the sitebuilder might not want end users to upload.txtfiles directly.Comment #28
alexpott@Pancho
is the current behaviour.
I think the current behaviour is wrong. Not allowing insecure updates and allowing php without txt should cause the users to see an error if they try to configure a field that way. The automatic rename and silently allowing .txt when the users has apparently chosen to not allow txt is weird.
Like, trying to upload blah.php will work but trying to upload blah.php.txt won't but uploading blah.php means you'll end up with a file called blah.php.txt. That is very confusing for a site administrator and user.
Comment #29
panchoTrue, so in the end, maybe current behavior turns out to be not so wrong at all? Let me investigate this a bit.
Comment #30
alexpott@Pancho sure investigate. But please ensure that the following is covered:
Here's yet-another-reason we the current behaviour is wrong. On a modern browser if you download the file and try to re-upload it it will not allow you because it will prevent non-allowed extensions at the browser level before they even hit Drupal.
Comment #31
panchoIndeed, the current behavior is clearly wrong.
Obviously, we should only accept
.phpfiles if.phpextension is allowed. However, if the extension is allowed, we have two options how to implement this in a way every sitebuilder would expect it to be:.phpfile might be accepted no matter whether in the end it is stored with its original extension or whether it is renamed to.txtfor security reasons..phpfile might even bypass the security check, as in the end, the sitebuilder voluntarily decided to allow.phpfiles and might have a proper usecase for exactly this.Obviously, the second option might be risky and should be accompanied by a security warning, but in the end, if a sitebuilder wants
.phpfiles to be allowed, they might know what they're doing.Still, as long as the latter usecase has not been substantiated, I'd tend to stick with the inherently safer variant 1.
Don't think so. If the sitebuilder wants to configure a particular file field just for
.phpfiles, they don't want people to upload all kinds of.txtfiles, just because.phpare internally renamed. If the sitebuilder wants to accept both, they may add both extensions.Comment #32
alexpottThe intention of the rename is to cope with situations where a user has configured a file field to allow all extensions. I.e. where allowed extensions equals an empty string. In this instance we do not want insecure files to be uploaded - hence the reasonable strategy to rename to add a .txt extension.
There is a 0.1% use-case where a site builder configures a file field to allow php files and does not enable
allow_insecure_uploads. We should not bend over backwards for this use-case. We should inform site builders that they need to add txt as an allowed extension because this is the extension the uploaded file will have. This new error also has the added benefit of telling a site builder that what they are intending to do is weird and to be honest not recommended.Still need to add UI tests for the new error and update path to take care of existing fields.
Comment #33
alexpottWhoops
Comment #34
alexpottHere's a UI test. Now we need an update path test.
Comment #38
alexpottNice - adding the post update found #3033494: SiteConfigureForm can install the file module without the field module
Here I fix the
drupal-8.6.0.bare.testing.php.gzto have field module installed.Comment #39
panchoTrue. However, this doesn’t answer my question why the admin needs to accept .txt files in the front end, just because internally, .php files are renamed .php.txt.
[edit: plus allowing renamed files to bypass the extension check would mean no string addition, so fixable in 8.6.x.]
However, I really don’t want to wreck anyone’s nerves arguing over this. Feel free to go ahead. Your approach does fix the reported bug, and that might be just enough.
Comment #40
alexpott@Pancho I answered
Already here was my answer:
You disagreed with my reasoning.
From my point of view, users can download files directly from the node edit form using a right click - they would then not be able to reupload this file. Further more when uploading to a multi value field they see a list of already uploaded files and the allowed extensions and files which don't match that rule. But if they try to upload a file with a match extension they won't be able to.
Also
- it's not an internal rename - it is renamed file, the file entity has the new filename and google / the world sees the file as a txt file.
Comment #41
pancho@alexpott: You have a valid point (allowing to re-upload the file), so do I (disallowing .txt files unrelated to security renames).
In the end, both approaches mean the original bug gets fixed, and that's probably more important than anything else. So I'm really fine with focussing on that! :)
Does the
drupal-8.6.0.bare.testing.php.gzbelong here or in #3033494: SiteConfigureForm can install the file module without the field module? In the latter case, the other issue would be a blocker (plus major for blocking a major bug).Comment #42
alexpottThe changes to
drupal-8.6.0.bare.testing.php.gzcan be here or there. We can just re-roll after whichever one gets in first. This change proves the change todrupal-8.6.0.bare.testing.php.gzworks as expected. The change already has testing of its specific bug.Comment #43
alexpottBlockers are in.
Comment #44
alexpottUpdated the issue summary.
Comment #45
alexpottWe have test coverage of the UI changes and the update path.
Comment #46
alexpottI'm not entirely sure that we need a change record for this change as existing sites function without change because we provide an update path and the user is informed about how to configure the fields in the the UI.
Comment #47
wim leersI can't find anything to nitpick about 😮. There's explicit test coverage that looks great, even for
FileUploadRestResource👌Comment #49
dwwMostly looks great. I agree with the direction this is going. The current behavior is definitely problematic and weird.
However, I think the UI text needs a bit more help before this is RTBC. A few other nits:
UX concern: I think this message needs the word "also". As it is, it's not clear we're saying you can put "js" in this list as long as you also include "txt", etc. I think this would be more clear:
"The extension %extension is insecure. In order to allow it to be uploaded, also allow the "txt" extension."
However, even that's still not great, since we don't say anywhere else that we rename "insecure" files to .txt. At the risk of being too verbose, perhaps this:
"The extension %extension is insecure, and will be renamed to @extension_.txt. In order to allow %extension files to be uploaded, also allow the "txt" extension."
(or something)?
Finally, it's a little weird that %extension is an italicized placeholder while "txt" is quoted. Maybe we can/should be consistent about that and always format references to extensions in this message the same way?
Ugh to be adding code to one of the last deprecated WebTestBase test classes. I guess we'll just move all this again when that's finally killed.
If we address point #1, this spot also needs an update.
Shouldn't we also assert the page response here, too?
Assert page responses at these spots, too?
Minor nit: Why is this split onto 2 lines when it'd easily fit in 80 chars? Do we consider the newline ->save(); more readable for some reason?
cuz, we don't do that consistently if that's what we intend...
Comment #50
alexpott@dww thanks for the review - especially looking at the UI text.
1. I've addressed this by being more explicit -
The extension php is insecure. In order to allow files with this extension to be uploaded add the txt extension as well.-- I've also placeholdered the txt since this is not translatable.2. Yep stuff takes time - this is one of the last.
3. Fixed
4. I don't think so. It's going to be a 200 - if we had to assert that everywhere then we'd be adding 100s of these - if it was not a 200 then I'd agree. I think as long as we have 1 assertion about the expected output then we're good. Is there a reason you think different?
5. See answer to 4.
6. Dunno maybe PHPStorm being clever - fixed.
7. Indeed.
Comment #51
dww"The extension php is insecure. In order to allow files with this extension to be uploaded add the txt extension as well." is definitely better, thanks.
I still kinda wish we said why. Either here, or perhaps a link to a d.o handbook page about it?
I think we should tag this for UX review and get some more eyes on this issue.
Comment #52
dwwp.s. re #50.4 and 5: I agree with you. I've just seen assert 200's everywhere in core tests, and assumed it was standard practice to basically always do that before asserting anything else after a new request. *shrug*.
Comment #53
dwwRefreshing the summary a bit to make it easier for the UX review.
Also, from an "API-First Initiative" standpoint, if you can create a file field through the API, not just the field UI, don't we need the validation that txt is also in the allowed list if anything insecure is at some lower level than
$form_state->setError()? Admitting my ignorance here about the actual API-First-ness of core. ;) Not sure if/how that works.Thanks,
-Derek
Comment #54
alexpottI also think we could consider adding txt when adding a malicious file extension via UI. And telling the user we've done this rather than erroring.
Re. API first creation of fields. Well config validation is something we're working on but is not all there atm. Field config validation should be attempted altogether - I don't think this issue should add the first piece.
Comment #55
dwwRe: #54.A: Auto-adding .txt seems weird, but I'll let the UX team respond to that part. ;)
Re: #54.B and API-first creation of fields: Duly noted. Makes sense. I had the thought, so I wanted to raise it, but I'm totally satisfied that we can't solve it here.
I pinged #ux in Slack to try to get a review of this on the weekly UX call (which is today). Let's see what happens.
Thanks!
-Derek
Comment #56
dwwFurther updates to the summary to make the UI text changes totally explicit for reviewers without having to read the patch.
Comment #57
wim leersFor @dww's information: see "full config entity support in #3002188: REST: top priorities for Drupal 8.7.x — specifically #2869792: [meta] Add constraints to all config entity types.
Comment #58
benjifisherUsability review
We discussed this at the end of the weekly Drupal usability meeting today (2019-02-26).
hook_help()to be displayed on/admin/help/file.I will also add a few screenshots. You might add them to the IS to help further review.
Regarding (1): let's start with the text shown when someone tries to upload an "unsafe" file: "For security reasons, your upload has been renamed to index.php.txt." Can we add to the help text for the "Allowed file extensions" setting, something like "For security reasons, '.txt' will be added to any file ending in '.php'."? Ideally, figure out which of the allowed extensions are unsafe; my suggestion assumes just 'php'.
It is OK if the additional text only appears when the settings page is reloaded: save settings, then edit them again and see the extended text.
As for (2), how about changing "add" to "allow"? Also, add a comma and be consistent with "the extension ..." instead of "the ... extension": "The extension php is insecure. In order to allow files with this extension to be uploaded, allow the extension txt as well."
I notice that if I try to allow "cgi" as well as "php", only the first is mentioned in the warning message. I guess that is OK, especially if you address (1).
For (3), there is already a section on "Allowing file extensions", so it is clear where to add further details.
For (4), my typical annoyance is with password forms. Either I am not using a password manager and I choose something too short or else I am using a password manager and it fills in something with characters that are not allowed. Either way, I get annoyed that the first time I am told about the rule is in an error message.
I guess you do not have to worry about (4) as long as you address (3).
I will leave the "Needs usability review" tag until these points are addressed.
Comment #59
alexpott@benjifisher thanks for the review. Should have a patch up to address most of the points. However re the "allow" wording...
The double allow doesn't really work for me. Also in order to allow text files you need to add the txt extension so it is telling you what to do. Which seems to be good UX to me.
Comment #60
benjifisher@alexpott:
Here are some more possibilities: In order to allow files with this extension to be uploaded, ...
The first is the one I do not like, and the second is the one you do not like. I think the longest is the most explicit, but it is also the longest. ;) Does the second "allow" look any better after "also"?
Comment #61
alexpott@benjifisher I think we need to tell the user what to do. Saying allow does not do that.
Going back to the whole message. How about:
It's on point, explains exactly what to do and why you are being asked.
Comment #62
xjmComment #67
yoroy commented> The upload has been renamed to index.php.txt for security reasons
Maybe remove "reasons":
The upload has been renamed to index.php.txt for security.
(because "reasons" in the abstract does not really add information. "because reasons" is a kind of hand-wavy expression these days, no?)
Riffing on #61:
Add txt to the list of allowed extensions to securely upload files with a php extension.
with added explanation:
Add txt to the list of allowed extensions to securely upload files with a php extension. The txt extension will then be added automatically.
I wouldn't mind the more verbose version here as these are tricky things to consider.
Comment #68
benjifisherHow is this issue affected by https://www.drupal.org/sa-core-2020-012?
Comment #69
alexpottRe-rolled for 9.2.x. Re #68 - that SA did not change this behaviour.
Still need to account for the UX feedback. The new patch adds less strings because it fallbacks back to the security behaviour in file_validate()... that exists in HEAD...
So the whole "security reasons" debate is out-of-scope here - sure we can open a follow-up to improve said text but it's not really part of this change.
Still need to address the #61 part of the UX feedback.
No interdiff because nearly 2 years since last patch.
Comment #70
alexpottChanging the UI test to @yoroy's suggestion in #67
Comment #72
alexpottOn reviewing this I've realised that we can remove some dead code and make some code a bit clearer.
Comment #73
larowlanCould we use the simpler
/\btxt\bhere instead?https://www.phpliveregex.com/p/yJT
nit: > 80
should we
trim()this here to make sure we don't end up with two spaces when we're appending' txt'nit: missing a word after insecure here?
perhaps
insecure (one|extension) is allowedthese are strings so should we be using TRUE as the third argument to in_array
because this is in a
foreachloop, we may ending up setting multiple errors with essentially the same text for the one field. Should we instead collect all insecure extensions and then print the message once with the list if the said list is not empty?And if so, would array_filter be a better language construct to use than foreach
Comment #74
anmolgoyal74 commentedaddressed #74.
Comment #76
alexpottThis is test is allowed to be longer than 80 - it is used in the UI for update descriptions. Also it should be "Add" and not "Adds".
:) this needs to be either one OR extension. Let's go for extension.
This doesn't look correct or easy to read. I think that what was here before was easier to understand and read. You don't get multiple errors. Each form element can only have one error.
Comment #77
anmolgoyal74 commentedComment #78
alexpottUnfortunately removed the TRUE - which was a good change see #73.5
One problem this code has is what if a user add both php and js to the list of allowed extensions. We'll only raise an error on one of the extensions.
I think this is okay because adding the txt extension will fix it. So what this points out is that we can do:
Adding the
break;will prevent unnecessary looping/calls to $form_state->setError(). And it's a bit more explicit about what matters.Comment #79
anmolgoyal74 commentedComment #80
dwwMostly looking great, thanks for all the work in here! The actual changes are very small and an improvement in behavior. Test coverage is solid and clear. Only a handful of cosmetic nits about comments and code style.
Is it worth a new test-only patch upload?
After a few minor edits, the issue summary is mostly in good shape. Also, crossed off UX review from remaining tasks per previous comments. Do we need screenshots for the UI changes section?
Is it fair to say there are no API changes when we're changing the behavior of the JSONAPI + REST endpoints? Files that used to be allowed would be rejected after the change, unless the site is reconfigured. Sort of a gray area for "API changes".
Seems this needs a change record, especially since it can impact JSONAPI/REST clients. That's the main reason I'm NW'ing this. None of the points below are really blockers. Otherwise I'd RTBC this.
Wouldn't it be better to add these to the global dictionary instead of each file we use it?Edit: Guess not. ;) I grep'ed and see we're doing it in a few spots. Note: we mostly (but not entirely) use "cSpell:ignore" for these...
We're removing the old comment about .txt handling. It'd be nice to explain the preg_match() right above this if().
It's already a little unfortunate that the existing comment explains the non-existent "else" case, not what the code below it is actually doing.
Perhaps:
If there is no file extension validation at all, or the site allows 'txt' extensions and the file would otherwise pass validation, rename it. If the file will be rejected anyway due to...
(re-wrapped to 80 chars).
Wondering if this function name is what we want to commit. Maybe:
file_post_update_add_txt_extension_if_allows_insecure()?
Nits:
"Determine if this
isfield uses an item definition that extends FileItem."Hyper nit: could use a comma after "allowed".
a) Standards are to document outside the if.
b) This is a bit wordy, and doesn't really add much beyond the code. How about:
// If any insecure extension is allowed, add the 'txt' extension.
Although this is a bit clearer, it isn't needed, is it? Out of scope?
How about?
// Set an error if neither 'txt' extensions nor insecure uploads are allowed.
Hyper nit: 'PHP' is an acronym (a recursive one, no less!), while 'txt' is an abbreviation for 'text'. So we don't need caps 'TXT'.
Should we also assert there's no 'Saved $field_name configuration' at this point?
The comment from below might be helpful above, too. I did a double-take when I first saw this...
Doesn't this need a type and an explanation?
Off topic, but I wonder how long this "temporary" class is going to be part of core. ;)
Maybe need to say:
Add 'php' and 'txt' as allowed extensions. Allow insecure...
Hyper nit: As below, the ->save() would easily fit on the previous line. Maybe that'd be out of scope. ;)
But if we don't, maybe we need to split the ->save() onto a newline later to be consistent?
Thanks!
-Derek
Comment #81
alexpottThanks for the review @dww.
Re #80:
cSpell:ignore@dww what do you think a change record needs to say? We've got an update function and allowing insecure extensions is super super uncommon.
Comment #82
dwwThanks for the fixes and improvements! Almost there. A few final minor nits:
Not going to NW over these, since other reviews are still welcome and none of these should block RTBC:
a) "or allows" here is still clumsy. "..., or the site allows..."?
b) should we use "... allows the .txt extension" for consistency with the rest of the patch?
s/'txt'/.txt/ ?
.txt
Otherwise, 👍. This is more clear than before, and more correct than what I proposed. 😉 Thanks!
Hyper nit: .txt
If we're rerolling, maybe remove this newline?
.php and .txt here?
Re: CR, here's what I had in mind: https://www.drupal.org/node/3194107
Needs version info filled in, and to be published (if we agree it's worth keeping).
Thanks again!
-Derek
Comment #83
alexpott@dww thanks for the review.
1. The site might have some form element that do allow and some that don't ... the site is not really a context we can talk about. It feels funny to be re-writing this so much. It's all going to be removed in #3032390: Add an event to sanitize filenames during upload - anyhow re-wrote it again. Re... 'txt' vs .txt /shrug.
2. Sure
3. Here I think this is correct the list does not have a . in it.
4. Fixed
5. That's against coding standards...
6. Re-worked the entire thing so it is easier to read.
Re the CR
If someone updates a field and tries to remove the added txt extension they will get an error because the insecure extension will be in the list. Still not really getting the point of a CR. Once the update has occurred a site's behaviour doesn't change - unless they try to remove the txt extension from the list - but given they were allowing an insecure extension they were already getting .txt files so why would you do that and how does the CR help more than the form error?
Comment #84
dwwThanks, @alexpott!
Sorry for being this pedantic. I've just had so many issues held up for similarly trivial pedantic nitpicks over comments that I thought that's what we "need" for something to be committed to core, and that I'm trying to find all the "problems" before this is RTBC.
1. 👍
5. Sorry, dreditor gave crappy context. That wasn't the newline I meant. Doesn't matter.
6. 👍
Re: CR: I don't know. Again, I was err'ing on the side of "caution" and providing one. I think it doesn't hurt to call out this behavior change with a CR. But you're probably right that it doesn't really matter and folks will find out via the admin UI. It's true that behavior won't change once the DB update runs. It's also true that sites can change their file config at any time and potentially "break" JSONAPI clients that used to be able to upload files that are now rejected.
Anyway, thanks again for taking care of everything, and sorry for spending energy on relatively pointless comment cleanup. To that end, you left a double-word in #83:
'are' repeated.
Seems cruel to NW for that. So I'm just fixing it here and self-RTBC'ing. Hopefully I won't be struck down by lightning for breaking the rules. 😉
At least it's a comment in a test that will survive the rewrite from #3032390: Add an event to sanitize filenames during upload, so it's worth fixing.
Comment #85
larowlanAdding review/discussion credits
Comment #87
larowlan💬 Fixed on commit:
✅ Committed fd1d675 and pushed to 9.2.x. Thanks!
⏬ Because of the update hook, I think this would be minor eligible only, as much as I'd like to backport this to 9.1 for the sake of enhanced security.
➡️ Unpostponed the blocked #3032390: Add an event to sanitize filenames during upload
➡️ Published the change-record
➡️ Tagged for release notes and confirmed there's a release note snippet
🎶 This commit brought to you by Viet Nam by Minutemen, Pinch by CAN and Whatcha Drinkin' by Hüsker Dü