0935d388f0
Django has a `SECURE_PROXY_SSL_HEADER` setting[^1] which controls if it examines a header, usually provided by upstream proxies, to allow it to treat requests as "secure" even if the proximal HTTP connection was not encrypted. This header is usually the `X-Forwarded-Proto` header, and the Django configuration has large warnings about ensuring that this setting is not enabled unless `X-Forwarded-Proto` is explicitly controlled by the proxy, and cannot be supplied by the end-user. In the absence of this setting, Django checks the `wsgi.url_scheme` property of the WSGI environment[^2]. Zulip did not control the value of the `X-Forwarded-Proto` header, because it did not set the `SECURE_PROXY_SSL_HEADER` setting (though see below). However, uwsgi has undocumented code which silently overrides the `wsgi.url_scheme` property based on the `HTTP_X_FORWARDED_PROTO` property[^3] (and hence the `X-Forwarded-Proto` header), thus doing the same as enabling the Django `SECURE_PROXY_SSL_HEADER` setting, but in a way that cannot be disabled. It also sets `wsgi.url_scheme` to `https` if the `X-Forwarded-SSL` header is set to `on` or `1`[^4], providing an alternate route to deceive to Django. These combine to make Zulip always trust `X-Forwarded-Proto` or ``X-Forwarded-SSL` headers from external sources, and thus able to trick Django into thinking a request is "secure" when it is not. However, Zulip is not accessible via unencrypted channels, since it redirects all `http` requests to `https` at the nginx level; this mitigates the vulnerability. Regardless, we harden Zulip against this vulnerability provided by the undocumented uwsgi feature, by stripping off `X-Forwarded-SSL` headers before they reach uwsgi, and setting `X-Forwarded-Proto` only if the request was received directly from a trusted proxy. Tornado, because it does not use uwsgi, is an entirely separate codepath. It uses the `proxy_set_header` values from `puppet/zulip/files/nginx/zulip-include-common/proxy`, which set `X-Forwarded-Proto` to the scheme that nginx received the request over. As such, `SECURE_PROXY_SSL_HEADER` was set in Tornado, and only Tornado; since the header was always set in nginx, this was safe. However, it was also _incorrect_ in cases where nginx did not do SSL termination, but an upstream proxy did -- it would mark those requests as insecure when they were actually secure. We adjust the `proxy_set_header X-Forwarded-Proto` used to talk to Tornado to respect the proxy if it is trusted, or the local scheme if not. [^1]: https://docs.djangoproject.com/en/4.2/ref/settings/#secure-proxy-ssl-header [^2]: https://wsgi.readthedocs.io/en/latest/definitions.html#envvar-wsgi.url_scheme [^3]: |
||
---|---|---|
.github | ||
.tx | ||
.vscode | ||
analytics | ||
api_docs | ||
confirmation | ||
corporate | ||
docs | ||
help | ||
locale | ||
pgroonga | ||
puppet | ||
requirements | ||
scripts | ||
static | ||
stubs/taint | ||
templates | ||
tools | ||
var/puppeteer | ||
web | ||
zerver | ||
zilencer | ||
zproject | ||
.codecov.yml | ||
.codespellignore | ||
.editorconfig | ||
.eslintignore | ||
.eslintrc.json | ||
.gitattributes | ||
.gitignore | ||
.gitlint | ||
.mailmap | ||
.npmignore | ||
.npmrc | ||
.prettierignore | ||
.pyre_configuration | ||
.readthedocs.yaml | ||
.sonarcloud.properties | ||
CODE_OF_CONDUCT.md | ||
CONTRIBUTING.md | ||
Dockerfile-postgresql | ||
LICENSE | ||
NOTICE | ||
README.md | ||
SECURITY.md | ||
Vagrantfile | ||
manage.py | ||
package.json | ||
pnpm-lock.yaml | ||
prettier.config.js | ||
pyproject.toml | ||
stylelint.config.js | ||
tsconfig.json | ||
version.py |
README.md
Zulip overview
Zulip is an open-source team collaboration tool with unique topic-based threading that combines the best of email and chat to make remote work productive and delightful. Fortune 500 companies, leading open source projects, and thousands of other organizations use Zulip every day. Zulip is the only modern team chat app that is designed for both live and asynchronous conversations.
Zulip is built by a distributed community of developers from all around the world, with 74+ people who have each contributed 100+ commits. With over 1000 contributors merging over 500 commits a month, Zulip is the largest and fastest growing open source team chat project.
Come find us on the development community chat!
Getting started
-
Contributing code. Check out our guide for new contributors to get started. We have invested in making Zulip’s code highly readable, thoughtfully tested, and easy to modify. Beyond that, we have written an extraordinary 150K words of documentation for Zulip contributors.
-
Contributing non-code. Report an issue, translate Zulip into your language, or give us feedback. We'd love to hear from you, whether you've been using Zulip for years, or are just trying it out for the first time.
-
Checking Zulip out. The best way to see Zulip in action is to drop by the Zulip community server. We also recommend reading about Zulip's unique approach to organizing conversations.
-
Running a Zulip server. Self-host Zulip directly on Ubuntu or Debian Linux, in Docker, or with prebuilt images for Digital Ocean and Render. Learn more about self-hosting Zulip.
-
Using Zulip without setting up a server. Learn about Zulip Cloud hosting options. Zulip sponsors free Zulip Cloud Standard for hundreds of worthy organizations, including fellow open-source projects.
-
Participating in outreach programs like Google Summer of Code and Outreachy.
-
Supporting Zulip. Advocate for your organization to use Zulip, become a sponsor, write a review in the mobile app stores, or help others find Zulip.
You may also be interested in reading our blog, and following us on Twitter and LinkedIn.
Zulip is distributed under the Apache 2.0 license.