tl;dr: On 19 November we were notified of a security vulnerability on PythonAnywhere. It could not have been used to access files on your PythonAnywhere storage, including your code, nor was any personally identifiable data in our databases exposed. We also have no indication that it was ever exploited. It was fixed within two hours of notification. However, as a precautionary measure, we are recommending that if you use MySQL on PythonAnywhere, you should change your MySQL password.
Here are the details.
On 19 November a user notified us of a security issue. In certain specific circumstances, a paying PythonAnywhere user could get a list of running processes on one of our console servers. We identified the problem and pushed a fix live 90 minutes later. We have analysed our logs, and cannot see any evidence of anyone having exploited this vulnerability, but clearly we cannot rule out the possibility that someone did exploit it in the past, or did so in a way we can't detect.
If someone did exploit it, they would have been able to see the usernames of all people logged in to that console server, and the full command lines of any processes they were running. They would not have had access to any user file storage, or to any of the databases where we store any personally identifiable information (for example, names and addresses). We do not store credit card numbers on our servers.
However, because full command lines for running processes were visible, any private information that you had on command lines could have been seen by such an attacker. This includes any MySQL passwords, as these are visible in the command line if you happen to have a MySQL console (started from the "Databases" tab) running on the server. Postgres passwords are not at risk, as these are never specified on a command line (unless you explicitly put them on a command line yourself).
As an example of a non-MySQL credential that might have been potentially exposed, imagine you're using a third-party service that sends text messages. Normally you would interact with this using Python, but if you're just playing around, you might use curl from a bash console like this:
curl https://api.provider.com/send-message -u '[YOUR ACCOUNT CREDENTIALS]' -d "message=Hello" -d "number=+15551234567"
You can see that if an attacker had used the vulnerability at exactly the right time, they might have seen those credentials.
Once again, we have no evidence to suggest that anyone has exploited this security hole, and it is now fixed. However, we strongly advise that as a precautionary security measure, you change any MySQL password you have set on the "Databases" tab within PythonAnywhere, and that you also change any other login credentials that might have been exposed on a command line.
If you have any questions, please email us at support@pythonanywhere.com.