My question is why the plaintext password is even sent to them for password resets. There's zero reason for that. Shouldn't it just be validated and hashed by the webpage's script before sending?
There is no hashing done by web page scripts unless the site you are on uses Javascript for both the front end and back end (such as with React, node.js, etc.). Twitter is not one of those sites. However, values are encrypted over the line due to the SSL certificate (why you see HTTPS in the browser), but those values are decrypted on the server. The web server has to handle them somehow, and certainly can't validate anything, create new records (tweets, users, etc.) or update anything (such as your user profile) if it's just garbled encryption. It is not plaintext over the line.
This is inexcusable. Which developer had the bright idea to store passwords to a log file? That should never happen, ever. There's no reason for it.
Twitter was built on Ruby on Rails. It has, I believe, since migrated to another platform, but many of the concepts still remain, regardless of framework used. In Rails, for example, everything is logged - all parameters sent from a form (login info, new tweet message, profile settings, etc.) go to the log file, as well as database transactions and manual log messages.
In real world applications, regardless of programming framework used, logging either goes to an actual file on the drive of a server, or to a drain that feeds the log line-by-line to a service (so it can be searched or you can receive alerts on errors, etc.). There are also multiple levels of logging depending on what needs priority - everything from fatal and error messages that have higher priority, to info and debug messages for general system events. Things like this would have been an info message with parameters received from a client, POSTing to a particular endpoint. Those basic info and debug messages can be omitted from production logs, which does make debugging errors more difficult, but is often done for security purposes (the "use a sledgehammer to hammer in a nail" approach).
In most cases, the application framework employs sanitizers to mask sensitive parameters from being sent to the log (i.e. passwords, credit card numbers, social security numbers, etc.). This happens in a configuration file that isn't touched often, if ever, after the application is deployed on a website. Additionally, masking sensitive parameters occurs in production but not always in local development, since building, updating, or fixing features requires a higher level of knowledge of what's going on vs. once something has gone live.
My guess is they either accidentally turned off the sanitizer, changed the password field name or are using an alias field name to prevent bots (most likely case), or never masked it in the first place and decreased the log level for debugging purposes. It's a simple mistake that isn't easily apparent.
In any case, this happened on their end, they noticed it, and they let us know. There's no indication that anything has actually been accessed. And, even still, with most accounts using 2FA, most users staying perpetually logged in, and with API keys being how external applications authenticate to your Twitter account (not with your password), the likelihood of your password even showing up in the log is very slim anyway. I'm not saying you
shouldn't change your password (because you absolutely should), but this sounds much scarier than it actually is.