Repository: mitmproxy/mitmproxy

Issue:
Passphrase given in the command line is visible in the process list  
#### Problem Description
Mitmproxy accepts cert-passphrase as one of the command-line options. If the user gives a passphrase like this while running the mitmproxy, anyone having access to a command line on that server can see the passphrase by listing the running processes.

#### Steps to reproduce the behavior:
1. Create a self-signed certificate using openssl, make sure you give a passphrase for the certificate. 
2. Run mitmproxy/mitmdump/mitmweb with the command line options as shown
mitmdump --certs *.mydomain.com=mycert.pem cert-passphrase abcd 
3. Take a Linux terminal and issue the command ps -ef | grep mitm
4. You can see the passphrase given to mitmdump command in clear text

This is a security issue in my opinion. Some programs effectively hide such sensitive inputs that are given as command-line arguments. They do this by rewriting the command line args in an obfuscated manner and by rerunning the program by itself. In this way, the sensitive data that came along via command-line arguments will be visible for a split second, but that is still better than making them always visible as long as the program is running.




Discussion:
Thanks for raising this! This is an issue if you are running mitmproxy with a custom cert passphrase passed via the command line on a system where an adversary may be able to access the process table. To avoid this, you can specify cert_passphrase in `config.yaml` (https://docs.mitmproxy.org/stable/concepts-options/) or use an unencrypted certificate.

What alternative do you suggest? Rewriting the command line args increases complexity while not solving the issue but only making it slightly harder to exploit. Passing secrets as environment variables introduces its own set of issues. The only realistic options I can think of are:

 1. We can change the option to read a file containing the password, but that's really quite cumbersome and brings up the question why you don't decrypt the certificate in the first place. It also works really badly for people who use `config.yaml`.
 2. We can add a note in the option description.
I don't know how easily this could be done with the mitmproxy architecture and it's most likely not worth the effort for the gains, but couldn't mitmproxy ask for the password? So if the argument is given it will say "Please enter passphrase:" and only actually start after that.

> This is a security issue in my opinion. Some programs effectively hide such sensitive inputs that are given as command-line arguments. They do this by rewriting the command line args in an obfuscated manner and by rerunning the program by itself. In this way, the sensitive data that came along via command-line arguments will be visible for a split second, but that is still better than making them always visible as long as the program is running.

What about `.bash_history` or an equivalent? In your (hypothetical) server scenario, does the malicious user has permissions to see _other users'_ processes but cannot read other users files? I'm honestly not sure how this is handled in Linux.

Edit:

> will be visible for a split second

This sounds an awful lot like security by obscurity because it _feels_ more secure to a human. Can you link to some sources? I'm legit curious if and how this is actually done in the wild and what the threat model looks like.

Resolving patch:
diff --git a/mitmproxy/options.py b/mitmproxy/options.py
--- a/mitmproxy/options.py
+++ b/mitmproxy/options.py
@@ -47,7 +47,12 @@ def __init__(self, **kwargs) -> None:
         )
         self.add_option(
             "cert_passphrase", Optional[str], None,
-            "Passphrase for decrypting the private key provided in the --cert option."
+            """
+            Passphrase for decrypting the private key provided in the --cert option.
+
+            Note that passing cert_passphrase on the command line makes your passphrase visible in your system's
+            process list. Specify it in config.yaml to avoid this.
+            """
         )
         self.add_option(
             "ciphers_client", Optional[str], None,


Test patch: