Stop using environment variables for sending database passwords to MariaDB/MySQL #1009

Closed
opened 2025-02-25 22:27:47 +00:00 by witten · 3 comments
Owner

What I'd like to do and why

Providing passwords to MariaDB/MySQL via environment variable (e.g. MYSQL_PWD, which borgmatic uses today) is considered insecure. That's likely because the password can potentially be spied upon by child processes or, with root access, by looking at OS-level process metadata.

So as part of this ticket, modify the borgmatic MariaDB and MySQL hooks to pass the configured password to the database client command via a more secure mechanism.

Other notes / implementation ideas

One idea is to use the mariadb/mysql --defaults-extra-file flag to pass in a temporary file path that contains something like:

[client]
user=someusername
password=thepassword

However, this would have to be done very carefully to avoid potentially leaking the password via that file, say if the permissions aren't sufficiently restrictive or an attacker puts something at the file path before borgmatic writes to it.

Ideally, we could instead give the password to mariadb/mysql via an anonymous pipe like we do with the Borg encryption passphase, but that doesn't appear possible in this case.

A related alternative might be to pass a named pipe containing the password to --defaults-extra-file, but it's unclear that that's any more secure than a standard file for this use case.

### What I'd like to do and why Providing passwords to MariaDB/MySQL via environment variable (e.g. `MYSQL_PWD`, which borgmatic uses today) is [considered insecure](https://mariadb.com/kb/en/mariadb-environment-variables/). That's likely because the password can potentially be spied upon by child processes or, with root access, by looking at OS-level process metadata. So as part of this ticket, modify the borgmatic MariaDB and MySQL hooks to pass the configured password to the database client command via a more secure mechanism. ### Other notes / implementation ideas One idea is to use the `mariadb`/`mysql` `--defaults-extra-file` flag to pass in a temporary file path that contains something like: ```ini [client] user=someusername password=thepassword ``` However, this would have to be done very carefully to avoid potentially leaking the password via that file, say if the permissions aren't sufficiently restrictive or an attacker puts something at the file path before borgmatic writes to it. Ideally, we could instead give the password to `mariadb`/`mysql` via an anonymous pipe like we do with the Borg encryption passphase, but that doesn't appear possible in this case. A related alternative might be to pass a *named* pipe containing the password to `--defaults-extra-file`, but it's unclear that that's any more secure than a standard file for this use case.
Author
Owner

I actually managed to get a prototype working with an anonymous pipe!

$ ipython
...
In [1]: import os

In [2]: import subprocess

In [3]: import shlex

In [4]: read_file_descriptor, write_file_descriptor = os.pipe()
   ...: os.write(write_file_descriptor, '[client]\nuser=test\npassword=pass'.encode('utf-8'))
   ...: os.close(write_file_descriptor)

In [5]: subprocess.check_call(shlex.split("mariadb --defaults-extra-file=/dev/stdin --skip-ssl --host localhost --protocol tcp --skip-column-names
   ...:  --execute 'show schemas'"), stdin=read_file_descriptor)
information_schema
test
Out[5]: 0
I actually managed to get a prototype working with an anonymous pipe! ```python $ ipython ... In [1]: import os In [2]: import subprocess In [3]: import shlex In [4]: read_file_descriptor, write_file_descriptor = os.pipe() ...: os.write(write_file_descriptor, '[client]\nuser=test\npassword=pass'.encode('utf-8')) ...: os.close(write_file_descriptor) In [5]: subprocess.check_call(shlex.split("mariadb --defaults-extra-file=/dev/stdin --skip-ssl --host localhost --protocol tcp --skip-column-names ...: --execute 'show schemas'"), stdin=read_file_descriptor) information_schema test Out[5]: 0 ```
Author
Owner

This is implemented in main and will be part of the next release!

This is implemented in main and will be part of the next release!
Author
Owner

Released in borgmatic 1.9.13!

Released in borgmatic 1.9.13!
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
borgmatic-collective/borgmatic#1009
No description provided.