Repository: mitmproxy/mitmproxy

Issue:
Mitmdump option "--modify-headers" not working if any script added using "--scripts".
#### Problem Description
When using mitmdump with script specified using `--scripts` option - `--modify-headers` option is ignored.

#### Steps to reproduce the behavior:

**1.** Launch `mitmdump` with `--modify-headers`. 
My example: 
`mitmdump --set confdir=./.mitmproxy --flow-detail=2 --listen-port=8081 --modify-headers "/~q/Host/example.org"`
Output with `curl -x 127.0.0.1:8081 "http://www.trackip.net/ip?json"`:
```
127.0.0.1:50216: clientconnect
127.0.0.1:50216: GET http://www.trackip.net/ip?json
    User-Agent: curl/7.64.1
    Accept: */*
    Proxy-Connection: Keep-Alive
    Host: example.org
 << 404 Not Found 1.67k
    Date: Thu, 26 Nov 2020 10:06:22 GMT
    Content-Type: text/html; charset=UTF-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Set-Cookie: __cfduid=de786483d16a417b8768b01f604ef7f991606385181; expires=Sat, 26-Dec-20 10:06:21 GMT; path=/; domain=.example.org; HttpOnly; SameSite=Lax
    Lookup-Cache-Hit: 1
    Cache-Control: public, max-age=60
    Vary: Accept-Language, Accept-Encoding
    X-Cache: MISS
    X-Cache-Hits: 0
    CF-Cache-Status: MISS
    cf-request-id: 06a59dbd0500002d377c038000000001
    Report-To: {"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=NYIz48uJ3L6ZWGjd%2FEO4iNMvcCH0gsGhQhs4dpQ92t5e7W2I3wP1hp%2FoVqfbe94xjJbxqsuNcuvGp4dShFlFYVyn3W0hQX6RveNgJw%3D%3D"}],"group":"cf-nel","max_age":604800}
    NEL: {"report_to":"cf-nel","max_age":604800}
    X-Content-Type-Options: nosniff
    Server: cloudflare
    CF-RAY: 5f82cbdb3f422d37-KBP
127.0.0.1:50216: clientdisconnect
```
Header `Host` has been replaced with `example.org`, as expected.

**2.** Now launch `mitmdump` with `--modify-headers` and `--script`.
My example (using [jsondump.py](https://github.com/mitmproxy/mitmproxy/blob/master/examples/contrib/jsondump.py) script from `examples/contrib`): 
`mitmdump --set confdir=./.mitmproxy --flow-detail=2 --listen-port=8081 --modify-headers "/~q/Host/example.org" --scripts="/Users/ignisor/dev/proxy_lib/proxy/utils/jsondump.py"`
Output with `curl -x 127.0.0.1:8081 "http://www.trackip.net/ip?json"`:
```
Proxy server listening at http://*:8081
127.0.0.1:50412: clientconnect
127.0.0.1:50412: GET http://www.trackip.net/ip?json
    Host: www.trackip.net
    User-Agent: curl/7.64.1
    Accept: */*
    Proxy-Connection: Keep-Alive
 << 200 OK 76b
    Date: Thu, 26 Nov 2020 10:11:30 GMT
    Content-Type: text/plain
    Content-Length: 76
    Connection: keep-alive
    Set-Cookie: __cfduid=dd9e78e478768657490d8e5f8df1e870d1606385490; expires=Sat, 26-Dec-20 10:11:30 GMT; path=/; domain=.trackip.net; HttpOnly; SameSite=Lax
    CF-Cache-Status: DYNAMIC
    cf-request-id: 06a5a272a300003f0495bde000000001
    Report-To: {"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=E3IAN%2BfUeGUIqX75SqBx%2FwUVisP1%2Fa7iRdHS7P6wUzZI1A6zSkhSqR6sKJ82sZo9tWkzTrtPYVQq6xozPGJ82Y34hSyPXP%2Fo%2FW7kC%2FFulUc%3D"}],"group":"cf-nel","max_age":604800}
    NEL: {"report_to":"cf-nel","max_age":604800}
    Server: cloudflare
    CF-RAY: 5f82d3643d183f04-KBP
127.0.0.1:50412: clientdisconnect
```
Header `Host` **not changed** and still `www.trackip.net`.


#### System Information

> Mitmproxy: 5.3.0
> Python:    3.9.0
> OpenSSL:   OpenSSL 1.1.1h  22 Sep 2020
> Platform:  macOS-10.16-x86_64-i386-64bit



Discussion:
Thanks! This seems to affect addons which call `loader.add_option`. Minimal example:
```
# Good
$ mitmdump --modify-headers "/~q/Host/example.org"
# Bad
$ mitmdump --modify-headers "/~q/Host/example.org" --scripts examples/addons/options-simple.py

$ curl -x 127.0.0.1:8080 "http://www.trackip.net/ip?json"
```

Resolving patch:
diff --git a/mitmproxy/addons/modifyheaders.py b/mitmproxy/addons/modifyheaders.py
--- a/mitmproxy/addons/modifyheaders.py
+++ b/mitmproxy/addons/modifyheaders.py
@@ -63,8 +63,8 @@ def load(self, loader):
         )
 
     def configure(self, updated):
-        self.replacements = []
         if "modify_headers" in updated:
+            self.replacements = []
             for option in ctx.options.modify_headers:
                 try:
                     spec = parse_modify_spec(option, False)


Test patch: